Rework collisions using new vector class

master
GreenXenith 2020-02-24 16:12:42 -08:00
parent eece8b3244
commit 1e91631ed8
7 changed files with 105 additions and 60 deletions

2
.gitignore vendored
View File

@ -1,2 +1,2 @@
__pycache__/
.vscode/
.vscode/

15
game.py
View File

@ -40,11 +40,11 @@ tilemap = map.map["map"]
import controller
from player import Player
player = Player()
player.sprite.texture = spritesheet.SpriteSheet("textures/spritesheet.png", 32)
player.sprite.set_rect(player.sprite.texture.frame.get_rect())
player.sprite.texture = spritesheet.SpriteSheet("textures/character.png", 16, 24)
player.sprite.set_rect((0, 0, 16, 24))
# TODO: Use asset loader for spritesheets
player.sprite.texture.set_animation(0, 3, 0.2)
player.set_pos(1, 1)
player.sprite.texture.set_animation(0, 0, 0)
player.set_pos(1.1, 1.1)
CENTER = [winsize[0] / 2, winsize[1] / 2]
@ -62,7 +62,6 @@ while 1:
spritesheet.update(dtime)
# Move the map based on player position
pos = player.get_pos()
psize = player.sprite.rect.size
camera = [CENTER[0] - (psize[0] / 2 * SCALE), CENTER[1] - (psize[1] / 2 * SCALE)]
@ -71,11 +70,11 @@ while 1:
texture = assets.get(map.map["tiles"][tilemap[row][column]]["texture"])
tilesize = texture.get_rect().size[0]
screen.blit(pygame.transform.scale(texture, [SCALE * tilesize, SCALE * tilesize]), [
column * SCALE * tilesize - (pos["x"] * SCALE * METER) + camera[0],
row * SCALE * tilesize - (pos["y"] * SCALE * METER) + camera[1]
column * SCALE * tilesize - (player.pos.x * SCALE * METER) + camera[0],
row * SCALE * tilesize - (player.pos.y * SCALE * METER) + camera[1]
])
# Draw player based on camera position
screen.blit(pygame.transform.scale(player.sprite.texture.frame, [SCALE * tilesize, SCALE * tilesize]), camera)
screen.blit(pygame.transform.scale(player.sprite.texture.frame, [SCALE * player.sprite.texture.width, SCALE * player.sprite.texture.height]), camera)
pygame.display.flip()

View File

@ -47,4 +47,4 @@
[2, 0, 0, 0, 0, 0, 0, 4],
[8, 3, 3, 3, 3, 3, 3, 7]
]
}
}

27
map.py
View File

@ -1,6 +1,8 @@
import pygame
import json
import assets
import json
import pygame
from math import floor
from vector import Vector
class Map:
map = []
@ -10,11 +12,18 @@ class Map:
data = json.load(file)
for tile in data["tiles"]:
assets.load(tile["texture"])
self.map = data
def is_solid(self, x, y):
try:
return self.map["tiles"][self.map["map"][round(x)][round(y)]]["solid"]
except:
return False
def collides(self, pos, rect):
for y in range(int(floor(pos.y)) - 1, int(floor(pos.y)) + 2):
for x in range(int(floor(pos.x)) - 1, int(floor(pos.x)) + 2):
if not (x == pos.x and y == pos.y):
tile = self.map["tiles"][self.map["map"][y][x]]
if tile["solid"]:
rect2 = assets.get(tile["texture"]).get_rect()
if pos.x + (rect.width / 32) >= x and pos.x <= (x + rect2.width / 32) and \
pos.y + (rect.height / 32) >= y and pos.y <= (y + rect2.height / 32):
return True
return False

View File

@ -1,49 +1,66 @@
import pygame
import controller
from vector import *
from sprite import Sprite
METER = 32
class Player:
x = 0
y = 0
pos = Vector(0, 0)
hp = 100
mp = 50
xp = 0
dir = 0
vel = Vector(0, 0)
# TODO: Fix diagonal speed
speed = 1.5 # meters per second
def __init__(self):
self.sprite = Sprite()
def set_pos(self, x, y):
self.x = x
self.y = y
self.sprite.set_pos(self.x, self.y)
def get_pos(self):
return {"x": self.x, "y": self.y}
def set_pos(self, vec_or_x, y = None):
self.pos = vec_or_num(vec_or_x, y)
def update(self, dtime, map):
movedist = self.speed * dtime
if controller.is_down("up"):
pos = self.get_pos()
if not map.is_solid(self.sprite.rect.top - movedist, pos["x"]):
self.set_pos(pos["x"], pos["y"] - movedist)
if controller.is_down("down"):
pos = self.get_pos()
if not map.is_solid(self.sprite.rect.top + 1 + movedist, pos["x"]):
self.set_pos(pos["x"], pos["y"] + movedist)
vx = 0
vy = 0
if controller.is_down("left"):
pos = self.get_pos()
if not map.is_solid(pos["y"], self.sprite.rect.left - movedist):
self.set_pos(pos["x"] - movedist, pos["y"])
self.dir = 3
vx -= 1
if controller.is_down("right"):
pos = self.get_pos()
if not map.is_solid(pos["y"], self.sprite.rect.left + 1 + movedist):
self.set_pos(pos["x"] + movedist, pos["y"])
self.dir = 1
vx += 1
if controller.is_down("up"):
self.dir = 2
vy -= 1
if controller.is_down("down"):
self.dir = 0
vy += 1
self.vel.x = vx
self.vel.y = vy
oldx = self.pos.x
self.set_pos(self.pos.x + self.vel.x * self.speed * dtime, self.pos.y)
if map.collides(self.pos, self.sprite.rect):
self.set_pos(oldx, self.pos.y)
oldy = self.pos.y
self.set_pos(self.pos.x, self.pos.y + self.vel.y * self.speed * dtime)
if map.collides(self.pos, self.sprite.rect):
self.set_pos(self.pos.x, oldy)
if controller.is_down("up") or controller.is_down("down") or \
controller.is_down("left") or controller.is_down("right"):
self.sprite.texture.set_animation(self.dir * 4, (self.dir * 4) + 3, 0.2)
else:
self.sprite.texture.set_animation(self.dir * 4, self.dir * 4, 0)

View File

@ -1,10 +1,8 @@
import pygame
import assets
from vector import *
class Sprite:
x = 0
y = 0
texture = None
rect = None
@ -16,13 +14,3 @@ class Sprite:
def set_rect(self, rect):
self.rect = pygame.Rect(*rect)
def set_pos(self, x, y):
self.x = x
self.y = y
self.rect.x = self.x
self.rect.y = self.y
def get_pos(self):
return {"x": self.x, "y": self.y}

32
vector.py Normal file
View File

@ -0,0 +1,32 @@
def vec_or_num(x, y = None):
if (type(x) is int or type(x) is float) == True:
return Vector(x, y or x)
return x
class Vector:
def __init__(self, x = 0, y = 0):
self.x = float(x)
self.y = float(y)
def __repr__(self):
return "Vector {{x: {0}, y: {1}}}".format(self.x, self.y)
def apply(self, func):
return Vector(func(self.x), func(self.y))
def __add__(self, b):
vec = vec_or_num(b)
return Vector(self.x + vec.x, self.y + vec.y)
def __sub__(self, b):
vec = vec_or_num(b)
return Vector(self.x - vec.x, self.y - vec.y)
def __mul__(self, b):
vec = vec_or_num(b)
return Vector(self.x * vec.x, self.y * vec.y)
def __div__(self, b):
vec = vec_or_num(b)
return Vector(self.x / vec.x, self.y / vec.y)