Skip to content

Instantly share code, notes, and snippets.

/a_rts-3.py Secret

Created April 24, 2013 02:20
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save anonymous/605a0237bf03a1980a70 to your computer and use it in GitHub Desktop.
Save anonymous/605a0237bf03a1980a70 to your computer and use it in GitHub Desktop.
a_rts-3
# RTS prototype by "eliskan" - dementis.silenti@gmail.com
# Completed : Minimap tiles, beginning of unit implementation, aStar pathfinding
# TODO: HUD, resources, building managment, combat
from scene import *
from random import randint, choice
#from os import path, mkdir
from urllib import urlopen
from PIL import Image
from a_RTS_Core import * #Contains all core functions
CLIFF, SAND, MTN, GRASS, MTN_TO_WATER, WATER, SAND_TO_WATER = 0, 1, 2, 3, 4, 5, 6
VILLAGER, SOLDIER, ARCHER, CAVALRY, MAGE = 0, 1, 2, 3, 4
#Each 'node' contains data about its location, type, and parent nodes
class node (object):
def __init__(self, location):
self.x, self.y = location.x, location.y
self.type = choice([MTN_TO_WATER,SAND,MTN])#([MTN, SAND, MTN_TO_WATER, GRASS])
self.H = 0
self.neighbors = [None, None, None, None]
self.parent = None
self.population = 0
#Units
class unit (object):
def __init__(self, location, type=SOLDIER, current_node = None):
self.x, self.y = location.x, location.y
self.type = type
self.vel = Point(0,0) #Velocity
self.selected = False
self.node = current_node #Current node
self.target = -1
self.target_path = []
#Draw map draws the grids
def draw_map(grid_size, grid_count, grid_pos, map_img, minimap=False, box_pos=None):
g = grid_size*grid_count
fill(0,0,0,0)
image(map_img,grid_pos.x,grid_pos.y+g,g,g*-1) #Hax draws image upside down to fix bug
if minimap:
fill(1,1,1,.5)
rect(box_pos.x-30, box_pos.y-25, 60,50)
return
def draw_status(self):
fill(0,0,0,0.5)
rect(0,718,self.size.w,30)
rect(0,0,self.size.w,100)
#background(0,0,0)
text("delay time: "+str(self.dt), 'Avenir-Black', 10, 20, 738, 6)
#text("x="+str(self.circle_pos.x)+" y"+str(self.circle_pos.y), 'Avenir-Black', 10, 400, 738, 6)
#text("nodes="+str(get_node(self.circle_pos.x, self.circle_pos.y, self.grid_count, True)),
# 'Avenir-Black', 10, 600, 738, 6)
#text("")
def get_node(x, y, grid_count, index=False):
x = int(round((x-30)/60))
y = int(round((y-30)/60))
if x < 0: x = 0
if y < 0: y = 0
if index: return x*grid_count+y
return Point(x,y)
class MyScene (Scene):
def setup(self):
self.grid_count = 15 #Number of columns and rows on the map.
self.minimap_size = 200./self.grid_count #Size of each node on minimap
self.minimap_position = Point(self.size.w-220,20)
self.minimap_box = Point(self.minimap_position.x+100,self.minimap_position.y+100)
self.map_size = 60 #Size of each node on real map
self.map_position = Point(10,10) #Current viewing position of map
self.ratio = ratios(200,self.map_size*self.grid_count) #Finds the ratio to translate to minimap
self.node_array = [] #An array containing every node (map square) on the board
self.target_path = [] #Will contain path for unit. TODO: add into unit class
self.resources = [0,0,0,0] #Water, food, stone, and wood. Not in use yet.
self.drag = False #Drag and drop
self.selected_units = [] #An array containing the units we selected.
for x in xrange(self.grid_count):
for y in xrange(self.grid_count):
self.node_array.append(node(Point(x,y)))
self.units = []
for x in xrange(40):
self.units.append(unit(Point(20,20))) #Each unit should replace "circle"
#self.node_array[0].population = 25
#FORCE FIRST ROW TO BE PASSABLE, HAX LAST ROW TO FIX VISUAL BUG
#temp = 0
for n in range(self.grid_count):
self.node_array[n].type = SAND
self.node_array[n*self.grid_count+self.grid_count/2].type = SAND
#Let's hax last row so it looks good until a better solution is found
last_node = n+self.grid_count*self.grid_count-self.grid_count
if self.node_array[last_node-1].type == SAND:
self.node_array[last_node].type = choice([MTN_TO_WATER, MTN, MTN])
elif self.node_array[last_node-1].type == MTN:
self.node_array[last_node].type = choice([MTN_TO_WATER, SAND, SAND])
else: self.node_array[last_node].type = choice([SAND, MTN])
#Now we need to set up each nodes neighbors for pathfinding.. TODO: Shorten.
for index, nodes in enumerate(self.node_array):
try: #To the left
if index-self.grid_count > -1:
if not self.node_array[index-self.grid_count].type == MTN_TO_WATER:
nodes.neighbors[3] = self.node_array[index-self.grid_count]
except: pass
try: #Right
if self.node_array[index+self.grid_count].y == nodes.y:
if not self.node_array[index+self.grid_count].type == MTN_TO_WATER:
nodes.neighbors[1] = self.node_array[index+self.grid_count]
except: pass
try: #Top
if self.node_array[index+1].x == nodes.x:
if not self.node_array[index+1].type == MTN_TO_WATER:
nodes.neighbors[0] = self.node_array[index+1]
except: pass
try: #Bottom
if self.node_array[index-1].x == nodes.x:
if not self.node_array[index-1].type == MTN_TO_WATER:
nodes.neighbors[2] = self.node_array[index-1]
except: pass
#Load images.
self.img = loadImage(folderPath,imgPath,urlPath)
tempImage = Image.new('RGBA', (self.grid_count*self.map_size,self.grid_count*self.map_size))
#TODO: SHORTEN THIS LOOP!!
#Iterate through nodes, to place the image tiles for each node's 9 parts.
#Nodes depend on eachother for drawing so they blend into their neighbors.
for index, nodes in enumerate(self.node_array):
im = cropImage(self.img,LAND[nodes.type])
im_corners = cropImage(self.img,Point(LAND[nodes.type].x,1))
for pos_x in xrange(3):
for pos_y in xrange(3):
try:
temp_node = -1
g_index = index
neighbors = []
if pos_x==1 and pos_y==1: #Center tile
im_small = cropImage(im,Point(1,1),Size(20,20))
elif pos_x==0 and pos_y==1: #Left side, centered.
g_index -= self.grid_count
for neighbor in [-1,0,1]:
neighbors.append(self.node_array[g_index+neighbor].type)
if nodes.type == neighbors[1]: im_small = cropImage(im,Point(1,1),Size(20,20))
else: im_small = cropImage(im,Point(pos_x,pos_y),Size(20,20))
elif pos_x==2 and pos_y==1: #Right side, centered.
g_index += self.grid_count
for neighbor in [-1,0,1]:
neighbors.append(self.node_array[g_index+neighbor].type)
if nodes.type == neighbors[1]: im_small = cropImage(im,Point(1,1),Size(20,20))
else: im_small = cropImage(im,Point(pos_x,pos_y),Size(20,20))
elif pos_x==1 and pos_y==0: #Top side, centered.
g_index -= 1
for neighbor in [self.grid_count*-1,0,self.grid_count]:
neighbors.append(self.node_array[g_index+neighbor].type)
if nodes.type == neighbors[1]: im_small = cropImage(im,Point(1,1),Size(20,20))
else: im_small = cropImage(im,Point(pos_x,pos_y),Size(20,20))
elif pos_x==1 and pos_y==2: #Bottom side, centered.
g_index += 1
for neighbor in [self.grid_count*-1,0,self.grid_count]:
neighbors.append(self.node_array[g_index+neighbor].type)
if nodes.type == neighbors[1]:
im_small = cropImage(im,Point(1,1),Size(20,20))
tempImage.paste( im_small, (nodes.x*60+pos_x*20,nodes.y*60+pos_y*20) )
else: im_small = cropImage(im,Point(pos_x,pos_y),Size(20,20))
elif pos_x==0 and pos_y==2: #Bottom left corner
neighbors = [self.node_array[g_index-self.grid_count].type,
self.node_array[g_index+1].type,
self.node_array[g_index-self.grid_count+1].type]
if neighbors[0] == nodes.type and neighbors[1]==nodes.type:
if neighbors[2] == nodes.type:
im_small = cropImage(im, Point(1,1),Size(20,20))
else: im_small = cropImage(im_corners,Point(0,1),Size(20,20))
elif neighbors[0] == nodes.type:
im_small = cropImage(im, Point(1,2),Size(20,20))
elif neighbors[1] == nodes.type:
im_small = cropImage(im, Point(0,1),Size(20,20))
else: im_small = cropImage(im, Point(pos_x,pos_y),Size(20,20))
elif pos_x==2 and pos_y==2: #Bottom right corner
neighbors = [self.node_array[g_index+self.grid_count].type,
self.node_array[g_index+1].type,
self.node_array[g_index+self.grid_count+1].type]
if neighbors[0] == nodes.type and neighbors[1]==nodes.type:
if neighbors[2] == nodes.type:
im_small = cropImage(im, Point(1,1),Size(20,20))
else: im_small = cropImage(im_corners,Point(1,1),Size(20,20))
elif neighbors[0] == nodes.type:
im_small = cropImage(im, Point(1,2),Size(20,20))
elif neighbors[1] == nodes.type:
im_small = cropImage(im, Point(2,1),Size(20,20))
else: im_small = cropImage(im, Point(pos_x,pos_y),Size(20,20))
elif pos_x==0 and pos_y==0: #Top left corner
neighbors = [self.node_array[g_index-self.grid_count].type,
self.node_array[g_index-1].type,
self.node_array[g_index-self.grid_count-1].type]
if neighbors[0] == nodes.type and neighbors[1]==nodes.type:
if neighbors[2] == nodes.type:
im_small = cropImage(im, Point(1,1),Size(20,20))
else: im_small = cropImage(im_corners,Point(0,0),Size(20,20))
elif neighbors[0] == nodes.type:
im_small = cropImage(im, Point(1,0),Size(20,20))
elif neighbors[1] == nodes.type:
im_small = cropImage(im, Point(0,1),Size(20,20))
else: im_small = cropImage(im, Point(pos_x,pos_y),Size(20,20))
elif pos_x==2 and pos_y==0: #Top right corner
neighbors = [self.node_array[g_index+self.grid_count].type,
self.node_array[g_index-1].type,
self.node_array[g_index+self.grid_count-1].type]
if neighbors[0] == nodes.type and neighbors[1]==nodes.type:
if neighbors[2] == nodes.type:
im_small = cropImage(im, Point(1,1),Size(20,20))
else: im_small = cropImage(im_corners,Point(1,0),Size(20,20))
elif neighbors[0] == nodes.type:
im_small = cropImage(im, Point(1,0),Size(20,20))
elif neighbors[1] == nodes.type:
im_small = cropImage(im, Point(2,1),Size(20,20))
else:
im_small = cropImage(im, Point(pos_x,pos_y),Size(20,20))
tempImage.paste( im_small, (nodes.x*60+pos_x*20,nodes.y*60+pos_y*20) )
except:
im_small = cropImage(im, Point(pos_x, pos_y),Size(20,20))
tempImage.paste( im_small, (nodes.x*60+pos_x*20,nodes.y*60+pos_y*20) )#pass
self.map_img=load_pil_image(tempImage)
self.minimap_img = load_pil_image(tempImage.resize((200,200), Image.ANTIALIAS))
def draw(self):
background(0, 0, 0)
draw_map(self.map_size, self.grid_count, self.map_position, self.map_img)
#Circle for demonstration and testing. Just bounces around
for unit in self.units:
if unit.selected: fill(1,0,0,1)
else: fill(0,0,1,1)
ellipse(unit.x+self.map_position.x,unit.y+self.map_position.y,10,10)
#ellipse(unit.x/self.ratio+self.minimap_position.x,
# unit.y/self.ratio+self.minimap_position.y,3,3)
if not unit.selected:
unit.x -= unit.vel.x
unit.y -= unit.vel.y
if unit.x < 0: unit.vel.x *= -1; unit.target_path=[]
elif unit.x > self.map_size*self.grid_count: unit.vel.x *=-1; unit.target_path=[]
if unit.y < 0: unit.vel.y *= -1; unit.target_path=[]
elif unit.y > self.map_size*self.grid_count: unit.vel.y *=-1; unit.target_path=[]
#Find path for units. TODO: Alter this for efficiency.
current_node = get_node(unit.x, unit.y, self.grid_count, True)
if current_node < 0 or current_node > len(self.node_array)-1: current_node = 0
break_loop=0
while len(unit.target_path)<=2:
break_loop+=1
unit.target = randint(0,self.grid_count*self.grid_count-1)
unit.target_path = aStar(self.node_array, self.node_array[current_node],
self.node_array[unit.target])
self.node_array = cleanNodes(self.node_array)
if break_loop>=100: break
if len(unit.target_path)==1 and self.node_array[current_node] == unit.target_path[0]:
unit.vel.x = 0
unit.vel.y = 0
elif current_node != unit.node:
if unit.node == None: unit.node == current_node
unit.node = current_node
unit.target_path = aStar(self.node_array, self.node_array[current_node],
self.node_array[unit.target])
#except: pass#List index out of range?
self.node_array = cleanNodes(self.node_array)
if len(unit.target_path)>1:
if unit.target_path[1].y > get_node(unit.x,unit.y,self.grid_count).y:
unit.vel.y=-1
elif unit.target_path[1].y < get_node(unit.x,unit.y,self.grid_count).y:
unit.vel.y=1
else: unit.vel.y*=0.4
if unit.target_path[1].x > get_node(unit.x,unit.y,self.grid_count).x:
unit.vel.x=-1
elif unit.target_path[1].x < get_node(unit.x,unit.y,self.grid_count).x:
unit.vel.x=1
else: unit.vel.x*=0.4
fill(1,1,0,.3)
for nodes in self.units[0].target_path:
rect(nodes.x*60+self.map_position.x, nodes.y*60+self.map_position.y, 60, 60)
draw_status(self)
draw_map(self.minimap_size, self.grid_count, self.minimap_position,
self.minimap_img, True, self.minimap_box)
if self.drag: #Drag and drop
fill(1,1,1,.4)
rect(self.drag[0].x, self.drag[0].y, self.drag[1].x, self.drag[1].y)
def touch_began(self, touch):
pass
def touch_moved(self, touch):
if self.drag:
self.drag[1] = Point(touch.location.x-self.drag[0].x, touch.location.y-self.drag[0].y)
#Check if the selection box is hitting the circle.
#The hittests wont work if drag[1] has negative numbers. So we fix that
self.selected_units = []
tempX, tempY = self.drag[0].x, self.drag[0].y
if self.drag[1].x < 0: tempX = self.drag[0].x + self.drag[1].x
if self.drag[1].y < 0: tempY = self.drag[0].y + self.drag[1].y
for unit in self.units:
if hit(Point(unit.x+self.map_position.x,
unit.y+self.map_position.y), Point(tempX, tempY),
Point(abs(self.drag[1].x),abs(self.drag[1].y))):
unit.selected = True
self.selected_units.append(unit)
else: unit.selected = False
elif hit(touch.location, self.minimap_position, Point(200,200)):
tempPoint=Point(self.minimap_position.x-touch.location.x,
self.minimap_position.y-touch.location.y)
self.map_position = Point(tempPoint.x*self.ratio+self.size.w/2,
tempPoint.y*self.ratio+self.size.h/2)
self.minimap_box = Point(touch.location.x, touch.location.y)
else: self.drag = [touch.location, Point(0,0)]
def touch_ended(self, touch):
if self.drag:
self.drag = False
return
if hit(touch.location, self.minimap_position, Point(200,200)):
return #Ignore all minimap clicks after this point.
#Controls unit pathfinding after being commanded to walk to a point
if self.selected_units:
target_node = get_node(touch.location.x-self.map_position.x,
touch.location.y-self.map_position.y, self.grid_count, True)
for unit in self.selected_units:
unit.target = target_node
current_node = get_node(unit.x, unit.y, self.grid_count, True)
unit.target_path = aStar(self.node_array, self.node_array[current_node],
self.node_array[target_node])
unit.selected = False
self.node_array = cleanNodes(self.node_array)
self.selected_units = []
else:
self.selected_units = []
for unit in self.units:
if not self.selected_units:
if hit(touch.location, Point(unit.x+self.map_position.x-20, unit.y+self.map_position.y-20), Point(40,40) ):
unit.selected = True
self.selected_units.append(unit)
else: unit.selected = False
run(MyScene())
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment