-
-
Save anonymous/605a0237bf03a1980a70 to your computer and use it in GitHub Desktop.
a_rts-3
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# 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