Basic move only client

This commit is contained in:
pjht 2020-05-12 07:20:00 -05:00
parent 76c3665cc7
commit 588803a2bb
11 changed files with 704 additions and 0 deletions

240
blocks.py Normal file
View File

@ -0,0 +1,240 @@
import pygame
import os
import lib.constants as constants
from lib.gameregistry import GameRegistry
from lib.block import Block
from lib.inventory import Inventory
dy_blocks={}
def make_block(klass_name,name,clear=False,drops=False):
def blk_init():
pass
def init(self,x,y,screen):
Block.__init__(self,x,y,screen)
self.setTextureName(name)
self.clear=clear
self.drops=drops
self.unlocalisedName=name
attr_table={
"unlocalisedName":name,
"__init__":init,
"init":blk_init,
}
klass=type(klass_name,(Block,),attr_table)
GameRegistry.registerBlock(klass,name)
Block.registerTexture(name)
glob=globals()
glob[klass_name]=klass
global dy_blocks
dy_blocks[klass_name]=name
return klass
make_block("BlockStone","stone")
make_block("BlockTree","tree",False,("wood",8))
make_block("BlockGrass","grass",True)
make_block("BlockWood","wood")
make_block("BlockCoal","coal_ore")
GameRegistry.registerFuel("coal_ore",8)
make_block("BlockIron","iron_ore")
make_block("ItemIronIngot","iron_ingot",False)
#make_block("ItemCoal","coal",False)
# class BlockDoor(Block):
# unlocalisedName="door"
# openDoor=pygame.image.load(os.path.join("tiles","door_open.png"))
#
# @classmethod
# def init(cls):
# GameRegistry.registerBlock(cls,cls.unlocalisedName)
# Block.registerTexture(cls.unlocalisedName)
#
# def __init__(self,x,y,screen):
# Block.__init__(self,x,y,screen)
# self.setTextureName(BlockDoor.unlocalisedName)
# self.unlocalisedName=BlockDoor.unlocalisedName
#
# def interact(self,inv):
# self.clear=not self.clear
# pygame.mixer.Sound("door.ogg").play().set_volume(0.2)
#
# def getTexture(self):
# if self.clear:
# return BlockDoor.openDoor
# else:
# return False
#
# def interactData(self):
# return {"clear":self.clear}
#
# def loadData(self,data):
# self.clear=data["clear"]
#
# class BlockWorkbench(Block):
# unlocalisedName="workbench"
#
# @classmethod
# def init(cls):
# GameRegistry.registerBlock(cls,cls.unlocalisedName)
# Block.registerTexture(cls.unlocalisedName)
#
# def __init__(self,x,y,screen):
# Block.__init__(self,x,y,screen)
# self.setTextureName(BlockWorkbench.unlocalisedName)
# self.unlocalisedName=BlockWorkbench.unlocalisedName
# self.inv=Inventory()
#
# def interact(self,inv):
# selected=inv.selected
# if selected!="":
# inv.remove(selected)
# self.inv.addTile(selected,1)
# else:
# if self.inv.inv in GameRegistry.recipes.values():
# out=""
# for outp,reqs in GameRegistry.recipes.items():
# if self.inv.inv==reqs:
# out=outp
# break
# inv.addTile(out,1)
# self.inv.clear()
#
# def interactData(self):
# return {"inv":self.inv}
#
# def loadData(self,data):
# self.inv=data["inv"]
#
# class BlockFurnace(Block):
# unlocalisedName="furnace"
# frames=[]
#
# @classmethod
# def init(cls):
# GameRegistry.registerBlock(cls,cls.unlocalisedName)
# Block.registerTexture(cls.unlocalisedName)
# for i in range(3):
# path=os.path.join("animation",cls.unlocalisedName,"{}.png".format(i))
# img=pygame.image.load(path)
# cls.frames.append(img)
#
# def __init__(self,x,y,screen):
# Block.__init__(self,x,y,screen)
# self.setTextureName(BlockFurnace.unlocalisedName)
# self.unlocalisedName=BlockFurnace.unlocalisedName
# self.frameno=0
# self.forward=True
# self.burn=False
# self.count=0
# self.inp=""
# self.inp_amount=0
# self.outp=""
# self.outp_amount=0
# self.fuel=""
# self.fuel_amount=0
# self.fuel_num=0
# self.originator=True
#
# def interact(self,inv):
# sel=inv.selected
# if sel!="":
# if sel in GameRegistry.fuels.keys():
# if self.fuel!="" and sel!=self.fuel:
# return
# self.fuel=sel
# self.fuel_num=GameRegistry.fuels[sel]
# self.fuel_amount+=1
# if self.inp!="":
# if self.burn==False:
# self.fuel_amount-=1
# self.burn=True
# else:
# if self.inp!="" and sel!=self.inp:
# return
# if not sel in GameRegistry.smelting.keys():
# return
# self.inp_amount+=1
# self.inp=sel
# if self.burn==False and self.fuel!="":
# self.fuel_amount-=1
# self.burn=True
# inv.remove(sel)
# else:
# if self.outp!="":
# inv.addTile(self.outp,self.outp_amount)
# self.outp=""
# self.outp_amount=0
# self.originator=True
#
# def getTexture(self):
# if self.burn:
# self.count+=1
# if self.count==10:
# self.update()
# self.count=0
# img=BlockFurnace.frames[self.frameno]
# if self.forward:
# self.frameno+=1
# if self.frameno>2:
# self.frameno=1
# self.forward=False
# else:
# self.frameno-=1
# if self.frameno<0:
# self.frameno=1
# self.forward=True
# return img
# else:
# return False
# self.mp_upd=True
#
# def update(self):
# self.fuel_num-=1
# if self.inp=="":
# self.burn=False
# return
# if self.fuel_num<=0:
# if self.fuel_amount<=0:
# self.burn=False
# self.fuel=""
# return
# else:
# self.fuel_amount-=1
# self.fuel_num=GameRegistry.fuels[self.fuel]
# if self.inp!="":
# if self.inp in GameRegistry.smelting:
# self.inp_amount-=1
# self.outp=GameRegistry.smelting[self.inp]
# self.outp_amount+=1
# if self.inp_amount<=0:
# self.inp=""
# if self.originator:
# self.mp_upd=True
#
# def loadData(self,data):
# self.frameno=data["frameno"]
# self.forward=data["forward"]
# self.burn=data["burn"]
# self.count=data["count"]
# self.inp=data["inp"]
# self.inp_amount=data["inp_amount"]
# self.outp=data["outp"]
# self.outp_amount=data["outp_amount"]
# self.fuel=data["fuel"]
# self.fuel_amount=data["fuel_amount"]
# self.fuel_num=data["fuel_num"]
# self.originator=False
#
# def interactData(self):
# self.mp_upd=False
# return {
# "frameno":self.frameno,
# "forward":self.forward,
# "burn":self.burn,
# "count":self.count,
# "inp":self.inp,
# "inp_amount":self.inp_amount,
# "outp":self.outp,
# "outp_amount":self.outp_amount,
# "fuel":self.fuel,
# "fuel_amount":self.fuel_amount,
# "fuel_num":self.fuel_num
# }

67
client.py Normal file
View File

@ -0,0 +1,67 @@
import pygame
import os
import random
import sys
import select
import socket
import pickle
import lib.constants as constants
from lib.gameregistry import GameRegistry
from lib.map import Map
from lib.character import Character
from lib.block import Block
from lib.player import Player
from lib.player_img import PlayerImg
from time import sleep
import pprint
import blocks
pygame.init()
screen=pygame.display.set_mode((constants.WINDWIDTH,constants.WINDHEIGHT))
running=True
move=False
direction=None
key_to_dir={
pygame.K_UP:"up",
pygame.K_DOWN:"down",
pygame.K_LEFT:"left",
pygame.K_RIGHT:"right"
}
map=Map(screen,None,0)
map.tiles={}
player=Player(0,0,map,screen,"PJHT","player_local")
player.direction="up"
while running:
for event in pygame.event.get():
if event.type==pygame.QUIT:
running=False
if event.type==pygame.KEYDOWN:
if event.key in key_to_dir.keys():
move=True
direction=key_to_dir[event.key]
elif event.type==pygame.KEYUP:
move=False
player.frame=1
key_states = pygame.key.get_pressed()
if key_states[pygame.K_UP]==1:
move=True
direction="up"
elif key_states[pygame.K_DOWN]==1:
move=True
direction="down"
elif key_states[pygame.K_LEFT]==1:
move=True
direction="left"
elif key_states[pygame.K_RIGHT]==1:
move=True
direction="right"
if move:
player.move(direction)
screen.fill([0,0,0])
map.draw(player.x,player.y)
player.draw()
pygame.display.flip()
sleep(0.1)

2
lib/__init__.py Normal file
View File

@ -0,0 +1,2 @@
from . import block,constants,gameregistry,map,character,inventory,player,player_img
__all__=["block","gameregistry","map","character","inventory","player","player_img"]

53
lib/block.py Normal file
View File

@ -0,0 +1,53 @@
from pygame.sprite import Sprite
import pygame.image
import os
from time import sleep
from . import constants
class Block(Sprite):
textures={}
background=pygame.image.load(os.path.join("tiles","{}.png".format(constants.BACKGROUND)))
@classmethod
def init(cls):
subclasses=cls.__subclasses__()
for klass in subclasses:
klass.init()
def __init__(self,x,y,screen):
super().__init__()
self.x=x
self.y=y
self.screen=screen
self.tname=None
self.clear=False
self.unlocalisedName=""
self.drops=False
self.mp_upd=False
def draw(self,x,y):
if self.tname==None:
raise Exception("No texture name for block. Did you forget to call setTextureName()?".format())
self.screen.blit(Block.background,(x*constants.TILESIZE,y*constants.TILESIZE))
texture=self.getTexture()
if texture==False:
texture=Block.textures[self.tname]
self.screen.blit(texture,(x*constants.TILESIZE,y*constants.TILESIZE))
def setTextureName(self,name):
if not name in Block.textures.keys():
raise Exception("{} is not a valid texture. Did you forget to call registerTexture(\"{}\")?".format(name,name))
self.tname=name
@classmethod
def registerTexture(cls,name):
Block.textures[name]=pygame.image.load(os.path.join("tiles","{}.png".format(name)))
def interact(self,inv):
pass
def getTexture(self):
return False
def interactData(self):
return None
def loadData(self,data):
pass

53
lib/character.py Normal file
View File

@ -0,0 +1,53 @@
from pygame.sprite import Sprite
import pygame.image
import os
from . import constants
class Character(Sprite):
@staticmethod
def loadFrames(type):
frames={}
dirs=["up","down","left","right"]
num_frames=3
for direction in dirs:
frame_array=[0,0,0]
i=0
while i<num_frames:
img_name="{}_{}.png".format(direction,i)
frame_array[i]=pygame.image.load(os.path.join("sprites",type,img_name))
i+=1
frames[direction]=frame_array
return frames
def __init__(self,x,y,type,map,screen,*groups):
super().__init__(groups)
self.x=x
self.y=y
self.screen=screen
self.frames=self.loadFrames(type)
self.frame=1
self.direction="right"
self.map=map
def draw(self):
img=self.frames[self.direction][self.frame]
self.screen.blit(img,(self.x*constants.TILESIZE,self.y*constants.TILESIZE))
def move(self,direction):
old_x=self.x
old_y=self.y
self.direction=direction
if direction=="up":
self.y-=1
elif direction=="down":
self.y+=1
elif direction=="left":
self.x-=1
elif direction=="right":
self.x+=1
self.frame+=1
if self.frame>2:
self.frame=0
tile=self.map.tileAt(self.x,self.y)
if not tile.clear:
self.x=old_x
self.y=old_y

12
lib/constants.py Normal file
View File

@ -0,0 +1,12 @@
TILESIZE=16
MAPWIDTH=64
MAPHEIGHT=64
PORTHEIGHT=32
PORTWIDTH=32
EXTRAROWS=1
CENTERX=15
CENTERY=15
WINDWIDTH=PORTWIDTH*TILESIZE
WINDHEIGHT=(PORTHEIGHT+EXTRAROWS)*TILESIZE
BACKGROUND="grass"
FONTSIZE=30

25
lib/gameregistry.py Normal file
View File

@ -0,0 +1,25 @@
class GameRegistry:
block_classes={}
recipes={}
smelting={}
fuels={}
@classmethod
def registerBlock(cls,klass,name):
if not klass in cls.block_classes.keys():
cls.block_classes[name]=klass
@classmethod
def registerCrafting(cls,reqs,result):
if not result in cls.recipes.keys():
cls.recipes[result]=reqs
@classmethod
def registerSmelting(cls,inp,outp):
if not inp in cls.smelting.keys():
cls.smelting[inp]=outp
@classmethod
def registerFuel(cls,name,amount):
if not name in cls.fuels.keys():
cls.fuels[name]=amount

51
lib/inventory.py Normal file
View File

@ -0,0 +1,51 @@
class Inventory:
def __init__(self):
self.inv={}
self.selected=""
def addTile(self,name,amount):
if name in self.inv.keys():
self.inv[name]+=amount
else:
self.inv[name]=amount
self.selected=name
def remove(self,name,num=1):
if not name in self.inv:
raise Exception("No {} in inventory".format(name))
amount=self.inv[name]
amount-=num
if amount<0:
raise Exception("Attempted to remove more {} than avalible".format(name))
self.inv[name]=amount
if amount==0:
del self.inv[name]
self.selected=""
def selPrev(self):
newsel=""
for item, count in self.inv.items():
if item==self.selected:
break
newsel=item
if newsel!="":
self.selected=newsel
def clearSel(self):
self.selected=""
def selNext(self):
newsel=""
ok_next=False
for item, count in self.inv.items():
if ok_next:
newsel=item
break
if item==self.selected:
ok_next=True
if newsel!="":
self.selected=newsel
def clear(self):
self.inv={}
self.selected=""

97
lib/map.py Normal file
View File

@ -0,0 +1,97 @@
import pygame
import random
from pygame.sprite import Group
from . import block,gameregistry
from . import constants
from .gameregistry import GameRegistry
from .block import Block
import pickle
class Map:
def __init__(self,screen,sock=None,uid=None):
super().__init__()
self.tiles={}
self.screen=screen
self.sock=sock
self.uid=uid
def send_str(self,sock,str):
sock.send((str+"\n").encode("utf-8"))
def recvall(self,sock):
BUFF_SIZE=4096
data=b''
while True:
part=sock.recv(BUFF_SIZE)
data+=part
if len(part)<BUFF_SIZE:
break
return data
def addTile(self,tname,x,y):
klass=GameRegistry.block_classes[tname]
tile=klass(x,y,self.screen)
self.tiles[(x,y)]=tile
def generateTile(self,x,y):
num=random.randint(0,101)
if num<5:
num=random.randint(0,101)
if num<50:
self.addTile("tree",x,y)
else:
self.addTile("stone",x,y)
else:
self.addTile(constants.BACKGROUND,x,y)
def draw(self,centerx,centery):
topleftx=centerx-constants.CENTERX
toplefty=centery-constants.CENTERY
x=topleftx
y=toplefty
while True:
tile=self.tileAt(x,y)
if tile:
tile.draw(x-topleftx,y-toplefty)
x+=1
if x==topleftx+constants.PORTWIDTH:
x=topleftx
y+=1
if y==toplefty+constants.PORTHEIGHT:
break
def tileAt(self,x,y):
try:
return self.tiles[(x,y)]
except KeyError as e:
if self.sock:
self.send_str(self.sock,"BLOCK_AT_POS")
self.send_str(self.sock,str(x))
self.send_str(self.sock,str(y))
data=self.recvall(self.sock)
block=pickle.loads(data)
if block==None:
name=""
num=random.randint(0,101)
if num<5:
num=random.randint(0,101)
if num<50:
name="tree"
self.addTile("tree",x,y)
else:
name="stone"
self.addTile("stone",x,y)
else:
name=constants.BACKGROUND
self.addTile(constants.BACKGROUND,x,y)
self.send_str(self.sock,"PLACE_BLOCK_AT")
self.send_str(self.sock,str(self.uid))
self.send_str(self.sock,str(x))
self.send_str(self.sock,str(y))
self.send_str(self.sock,str(name))
else:
block.screen=self.screen
self.tiles[(x,y)]=block
else:
self.generateTile(x,y)
return self.tiles[(x,y)]

71
lib/player.py Normal file
View File

@ -0,0 +1,71 @@
from lib.character import Character
import lib.constants as constants
from lib.inventory import Inventory
class Player(Character):
def __init__(self,x,y,map,screen,uname,type,*groups):
super().__init__(x,y,type,map,screen,*groups)
self.inv=Inventory()
self.uname=uname
def facingTile(self):
x=self.x
y=self.y
if self.direction=="up":
y-=1
elif self.direction=="down":
y+=1
elif self.direction=="left":
x-=1
elif self.direction=="right":
x+=1
if x>constants.MAPWIDTH-1:
return False
if x<0:
return False
if y>constants.MAPHEIGHT-1:
return False
if y<0:
return False
return (x,y)
def interact(self):
coords=self.facingTile()
if coords==False:
return
tile=self.map.tileAt(coords[0],coords[1])
name=tile.unlocalisedName
if name=="grass":
to_place=self.inv.selected
if to_place=="":
return
self.map.tiles[(coords[0],coords[1])]=None
self.map.addTile(to_place,coords[0],coords[1])
self.inv.remove(to_place)
else:
tile.interact(self.inv)
def attack(self):
coords=self.facingTile()
if coords==False:
return
tile=self.map.tileAt(coords[0],coords[1])
name=tile.unlocalisedName
if name=="grass":
return
self.map.tiles[(coords[0],coords[1])]=None
self.map.addTile("grass",coords[0],coords[1])
if tile.drops==False:
self.inv.addTile(name,1)
else:
drop=tile.drops[0]
amount=tile.drops[1]
self.inv.addTile(drop,amount)
def draw(self):
oldx=self.x
oldy=self.y
self.x=constants.CENTERX
self.y=constants.CENTERY
super().draw()
self.x=oldx
self.y=oldy

33
lib/player_img.py Normal file
View File

@ -0,0 +1,33 @@
from pygame.sprite import Sprite
import pygame.image
import os
import lib.constants as constants
class PlayerImg(Sprite):
@staticmethod
def loadFrames(type):
frames={}
dirs=["up","down","left","right"]
num_frames=3
for direction in dirs:
frame_array=[0,0,0]
i=0
while i<num_frames:
img_name="{}_{}.png".format(direction,i)
frame_array[i]=pygame.image.load(os.path.join("sprites",type,img_name))
i+=1
frames[direction]=frame_array
return frames
def __init__(self,x,y,screen,type,*groups):
super().__init__(groups)
self.x=x
self.y=y
self.screen=screen
self.frames=self.loadFrames(type)
self.frame=1
self.direction="right"
self.map=map
def draw(self,x,y):
img=self.frames[self.direction][self.frame]
self.screen.blit(img,(x*constants.TILESIZE,y*constants.TILESIZE))