GameBox 0.1.1__tar.gz → 0.1.3__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- gamebox-0.1.3/.gitignore +12 -0
- {gamebox-0.1.1 → gamebox-0.1.3}/PKG-INFO +3 -1
- {gamebox-0.1.1 → gamebox-0.1.3}/README.md +2 -0
- {gamebox-0.1.1 → gamebox-0.1.3}/pyproject.toml +1 -1
- {gamebox-0.1.1 → gamebox-0.1.3}/src/GameBox/__init__.py +6 -2
- {gamebox-0.1.1 → gamebox-0.1.3}/src/GameBox/_game.py +16 -1
- {gamebox-0.1.1 → gamebox-0.1.3}/src/GameBox/basics/_net.py +2 -0
- gamebox-0.1.3/src/GameBox/basics/_shapes.py +33 -0
- {gamebox-0.1.1 → gamebox-0.1.3}/src/GameBox/basics/cammera.py +7 -1
- gamebox-0.1.3/src/GameBox/helpers/_input.py +70 -0
- {gamebox-0.1.1 → gamebox-0.1.3}/src/GameBox/player/_player.py +19 -2
- gamebox-0.1.3/src/GameBox/player/_playerPhysics.py +192 -0
- gamebox-0.1.3/src/GameBox/tilemap/_collisionDef.py +34 -0
- gamebox-0.1.3/src/GameBox/tilemap/_tilemap.py +75 -0
- gamebox-0.1.3/tests/basicScreen.py +36 -0
- gamebox-0.1.3/tests/levelTiles.png +0 -0
- gamebox-0.1.3/tests/testMap.json +4 -0
- gamebox-0.1.1/src/GameBox/basics/_shapes.py +0 -23
- gamebox-0.1.1/src/GameBox/player/_playerPhysics.py +0 -104
- gamebox-0.1.1/tests/basicScreen.py +0 -31
- {gamebox-0.1.1 → gamebox-0.1.3}/LICENSE +0 -0
- {gamebox-0.1.1 → gamebox-0.1.3}/src/GameBox/basics/__init__.py +0 -0
- {gamebox-0.1.1 → gamebox-0.1.3}/src/GameBox/basics/utils.py +0 -0
- {gamebox-0.1.1 → gamebox-0.1.3}/src/GameBox/player/_playerControler.py +0 -0
gamebox-0.1.3/.gitignore
ADDED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: GameBox
|
|
3
|
-
Version: 0.1.
|
|
3
|
+
Version: 0.1.3
|
|
4
4
|
Summary: GameBox is a beginner-friendly Python package built on top of pygame, designed to make 2D game development faster and easier. It provides ready-to-use modules, utilities, and abstractions that let new developers create polished games without needing advanced coding knowledge—while still offering the flexibility for experienced coders to customize and extend.
|
|
5
5
|
Author-email: Sam Fertig <sfertig007@gmail.com>
|
|
6
6
|
License-Expression: MIT
|
|
@@ -14,6 +14,8 @@ GameBox is a lightweight 2D game framework built on pygame.
|
|
|
14
14
|
This is an early technical preview of a full engine rewrite.
|
|
15
15
|
APIs may change frequently.
|
|
16
16
|
|
|
17
|
+
github: {https://github.com/sfertig/GameBox}
|
|
18
|
+
|
|
17
19
|
Versioning
|
|
18
20
|
GameBox follows a modified semantic versioning scheme.
|
|
19
21
|
Versions starting with 0.x.x are experimental and may change without notice.
|
|
@@ -2,6 +2,8 @@ GameBox is a lightweight 2D game framework built on pygame.
|
|
|
2
2
|
This is an early technical preview of a full engine rewrite.
|
|
3
3
|
APIs may change frequently.
|
|
4
4
|
|
|
5
|
+
github: {https://github.com/sfertig/GameBox}
|
|
6
|
+
|
|
5
7
|
Versioning
|
|
6
8
|
GameBox follows a modified semantic versioning scheme.
|
|
7
9
|
Versions starting with 0.x.x are experimental and may change without notice.
|
|
@@ -5,7 +5,7 @@ GameBox makes it easy to build 2D games with graphics, sound, and UI in just a f
|
|
|
5
5
|
"""
|
|
6
6
|
|
|
7
7
|
|
|
8
|
-
__version__ = "0.
|
|
8
|
+
__version__ = "0.1.3"
|
|
9
9
|
__author__ = "Sam Fertig"
|
|
10
10
|
|
|
11
11
|
#____imports____
|
|
@@ -14,6 +14,8 @@ from .basics.cammera import Cammera
|
|
|
14
14
|
from .basics._shapes import Rect
|
|
15
15
|
from .player._player import Player
|
|
16
16
|
from .basics.utils import clamp, moveTward, zeroOut
|
|
17
|
+
from .tilemap._tilemap import TileMap
|
|
18
|
+
from.helpers._input import Keys
|
|
17
19
|
|
|
18
20
|
|
|
19
21
|
__all__ = [
|
|
@@ -23,6 +25,8 @@ __all__ = [
|
|
|
23
25
|
"Player",
|
|
24
26
|
"clamp",
|
|
25
27
|
"moveTward",
|
|
26
|
-
"zeroOut"
|
|
28
|
+
"zeroOut",
|
|
29
|
+
"TileMap",
|
|
30
|
+
"Keys",
|
|
27
31
|
]
|
|
28
32
|
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import pygame
|
|
2
2
|
import numpy as np
|
|
3
3
|
|
|
4
|
+
|
|
4
5
|
from .basics._net import Global
|
|
5
6
|
from .player._player import Player
|
|
6
7
|
|
|
@@ -9,7 +10,7 @@ class Game:
|
|
|
9
10
|
"""
|
|
10
11
|
Initialize the Game object.
|
|
11
12
|
|
|
12
|
-
|
|
13
|
+
Parameters:
|
|
13
14
|
width (int): The width of the game window.
|
|
14
15
|
height (int): The height of the game window.
|
|
15
16
|
bg_color (tuple): The background color of the game window.
|
|
@@ -26,8 +27,11 @@ class Game:
|
|
|
26
27
|
Global.game = self
|
|
27
28
|
self.objs = []
|
|
28
29
|
|
|
30
|
+
|
|
29
31
|
def update(self, frame_rate=60):
|
|
32
|
+
#clear collisions
|
|
30
33
|
Global.collisions.clear()
|
|
34
|
+
|
|
31
35
|
Global.dt = Global.clock.tick(frame_rate) / 1000.0
|
|
32
36
|
Global.screen.fill(Global.bgColor)
|
|
33
37
|
player = None
|
|
@@ -36,3 +40,14 @@ class Game:
|
|
|
36
40
|
else: obj.update()
|
|
37
41
|
if player != None: player.update()
|
|
38
42
|
pygame.display.update()
|
|
43
|
+
|
|
44
|
+
def get_screen(self):
|
|
45
|
+
return Global.screen
|
|
46
|
+
|
|
47
|
+
def quit(self):
|
|
48
|
+
#will save files later
|
|
49
|
+
for obj in self.objs:
|
|
50
|
+
if hasattr(obj, "_quit") and callable(obj._quit):
|
|
51
|
+
obj._quit()
|
|
52
|
+
|
|
53
|
+
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import pygame
|
|
2
|
+
import numpy as np
|
|
3
|
+
|
|
4
|
+
from ..basics._net import Global
|
|
5
|
+
|
|
6
|
+
class Rect:
|
|
7
|
+
def __init__(self, pos: tuple, size: tuple, color: tuple = (0, 0, 0), collision: bool = True):
|
|
8
|
+
self.x, self.y = pos
|
|
9
|
+
self.width, self.height = size
|
|
10
|
+
self.color = color
|
|
11
|
+
Global.game.objs.append(self)
|
|
12
|
+
self.collision = collision
|
|
13
|
+
|
|
14
|
+
def update(self):
|
|
15
|
+
width = self.width * Global.cam.scale
|
|
16
|
+
height = self.height * Global.cam.scale
|
|
17
|
+
if (Global.cam.follow) != (self):
|
|
18
|
+
x = self.x - Global.cam.x
|
|
19
|
+
y = self.y - Global.cam.y
|
|
20
|
+
elif (Global.cam.follow) == (self):
|
|
21
|
+
x = self.x
|
|
22
|
+
y = self.y
|
|
23
|
+
|
|
24
|
+
rect = pygame.Rect(x, y, width ,height)
|
|
25
|
+
if self.collision: Global.collisions.append(rect)
|
|
26
|
+
pygame.draw.rect(Global.screen, self.color, rect)
|
|
27
|
+
|
|
28
|
+
def move(self, x, y):
|
|
29
|
+
if (Global.cam.follow) != (self):
|
|
30
|
+
self.x += x
|
|
31
|
+
self.y += y
|
|
32
|
+
else:
|
|
33
|
+
Global.cam.move(x, y)
|
|
@@ -6,13 +6,14 @@ from ._net import Global
|
|
|
6
6
|
from ..basics.utils import moveTward
|
|
7
7
|
|
|
8
8
|
class Cammera:
|
|
9
|
-
def __init__(self):
|
|
9
|
+
def __init__(self, scale: float = 1.0):
|
|
10
10
|
self.x = 0
|
|
11
11
|
self.y = 0
|
|
12
12
|
Global.game.objs.append(self)
|
|
13
13
|
Global.cam = self
|
|
14
14
|
self.follow = None
|
|
15
15
|
self.diff = (0, 0)
|
|
16
|
+
self.scale = scale
|
|
16
17
|
|
|
17
18
|
def move(self, x, y):
|
|
18
19
|
self.x += x
|
|
@@ -28,3 +29,8 @@ class Cammera:
|
|
|
28
29
|
self.follow = target
|
|
29
30
|
print(target)
|
|
30
31
|
self.diff = (target.x - self.x, target.y - self.y)
|
|
32
|
+
|
|
33
|
+
def set_scale(self, scale: float = 1.0):
|
|
34
|
+
self.scale = scale
|
|
35
|
+
def change_scale(self, scale: float = 1.0):
|
|
36
|
+
self.scale += scale
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
import pygame
|
|
2
|
+
|
|
3
|
+
from ..basics._net import Global
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
class _keys:
|
|
7
|
+
def __init__(self):
|
|
8
|
+
|
|
9
|
+
#alphabet
|
|
10
|
+
self.a = pygame.K_a
|
|
11
|
+
self.b = pygame.K_b
|
|
12
|
+
self.c = pygame.K_c
|
|
13
|
+
self.d = pygame.K_d
|
|
14
|
+
self.e = pygame.K_e
|
|
15
|
+
self.f = pygame.K_f
|
|
16
|
+
self.g = pygame.K_g
|
|
17
|
+
self.h = pygame.K_h
|
|
18
|
+
self.i = pygame.K_i
|
|
19
|
+
self.j = pygame.K_j
|
|
20
|
+
self.k = pygame.K_k
|
|
21
|
+
self.l = pygame.K_l
|
|
22
|
+
self.m = pygame.K_m
|
|
23
|
+
self.n = pygame.K_n
|
|
24
|
+
self.o = pygame.K_o
|
|
25
|
+
self.p = pygame.K_p
|
|
26
|
+
self.q = pygame.K_q
|
|
27
|
+
self.r = pygame.K_r
|
|
28
|
+
self.s = pygame.K_s
|
|
29
|
+
self.t = pygame.K_t
|
|
30
|
+
self.u = pygame.K_u
|
|
31
|
+
self.v = pygame.K_v
|
|
32
|
+
self.w = pygame.K_w
|
|
33
|
+
self.x = pygame.K_x
|
|
34
|
+
self.y = pygame.K_y
|
|
35
|
+
self.z = pygame.K_z
|
|
36
|
+
|
|
37
|
+
#numbers
|
|
38
|
+
self.n0 = pygame.K_0
|
|
39
|
+
self.n1 = pygame.K_1
|
|
40
|
+
self.n2 = pygame.K_2
|
|
41
|
+
self.n3 = pygame.K_3
|
|
42
|
+
self.n4 = pygame.K_4
|
|
43
|
+
self.n5 = pygame.K_5
|
|
44
|
+
self.n6 = pygame.K_6
|
|
45
|
+
self.n7 = pygame.K_7
|
|
46
|
+
self.n8 = pygame.K_8
|
|
47
|
+
self.n9 = pygame.K_9
|
|
48
|
+
|
|
49
|
+
#special keys
|
|
50
|
+
self.enter = pygame.K_RETURN
|
|
51
|
+
self.escape = pygame.K_ESCAPE
|
|
52
|
+
self.space = pygame.K_SPACE
|
|
53
|
+
self.backspace = pygame.K_BACKSPACE
|
|
54
|
+
|
|
55
|
+
#arrow keys
|
|
56
|
+
self.up = pygame.K_UP
|
|
57
|
+
self.down = pygame.K_DOWN
|
|
58
|
+
self.left = pygame.K_LEFT
|
|
59
|
+
self.right = pygame.K_RIGHT
|
|
60
|
+
|
|
61
|
+
#mouse
|
|
62
|
+
self.mouse_x, self.mouse_y = 0, 0
|
|
63
|
+
def init(self): Global.game.objs.append(self)
|
|
64
|
+
|
|
65
|
+
def is_pressed(self, key): return pygame.key.get_pressed()[key]
|
|
66
|
+
|
|
67
|
+
def update(self): self.mouse_x, self.mouse_y = pygame.mouse.get_pos()
|
|
68
|
+
|
|
69
|
+
|
|
70
|
+
Keys = _keys()
|
|
@@ -16,6 +16,7 @@ class Player:
|
|
|
16
16
|
|
|
17
17
|
Global.game.objs.append(self)
|
|
18
18
|
Global.player.pos = pos
|
|
19
|
+
Global.player.player = self
|
|
19
20
|
|
|
20
21
|
|
|
21
22
|
def add_physics(self, speed: float = 1.0, gravity: float = 0.0, jump: float = 10.0, maxV: float = 10.0, airRes: float = 0.2):
|
|
@@ -24,8 +25,16 @@ class Player:
|
|
|
24
25
|
def update(self):
|
|
25
26
|
self.physics.update()
|
|
26
27
|
#debug rect
|
|
27
|
-
|
|
28
|
-
|
|
28
|
+
width = self.dim[0] * Global.cam.scale
|
|
29
|
+
height = self.dim[1] * Global.cam.scale
|
|
30
|
+
if (Global.cam.follow) != (self):
|
|
31
|
+
x = self.x - Global.cam.x
|
|
32
|
+
y = self.y - Global.cam.y
|
|
33
|
+
elif (Global.cam.follow) == (self):
|
|
34
|
+
x = self.x
|
|
35
|
+
y = self.y
|
|
36
|
+
rect = pygame.Rect(x, y, width, height)
|
|
37
|
+
pygame.draw.rect(Global.screen, self.color, rect)
|
|
29
38
|
|
|
30
39
|
#movement
|
|
31
40
|
def top_down_movement(self):
|
|
@@ -33,3 +42,11 @@ class Player:
|
|
|
33
42
|
|
|
34
43
|
def platforming_movement(self):
|
|
35
44
|
self.physics.platforming_movement()
|
|
45
|
+
|
|
46
|
+
def set_tilemap_sample(self, sample: int = 10):
|
|
47
|
+
"""
|
|
48
|
+
Sets the sample size for player physics collisions.
|
|
49
|
+
Is the radius of tiles that will be used to get tilemap collisions around player. Note:
|
|
50
|
+
The larger the sample size the longer it may take to calculate collisions per frame.
|
|
51
|
+
"""
|
|
52
|
+
self.physics.sample = sample
|
|
@@ -0,0 +1,192 @@
|
|
|
1
|
+
import pygame
|
|
2
|
+
import numpy as np
|
|
3
|
+
|
|
4
|
+
from ..basics._net import Global
|
|
5
|
+
from ..basics.utils import clamp, moveTward, zeroOut
|
|
6
|
+
|
|
7
|
+
class _playerPhysics:
|
|
8
|
+
def __init__(self, player, speed: float = 1.0, gravity: float = 0.0, jump: float = 0.0, maxV: float = 10.0, airRes: float = 0.2):
|
|
9
|
+
self.player = player
|
|
10
|
+
self.rect = pygame.Rect(self.player.x, self.player.y, self.player.dim[0], self.player.dim[1])
|
|
11
|
+
|
|
12
|
+
self.speed = speed
|
|
13
|
+
self.gravity = gravity
|
|
14
|
+
self.jump = jump
|
|
15
|
+
self.player = player
|
|
16
|
+
self.maxV = maxV
|
|
17
|
+
self.airRes = airRes
|
|
18
|
+
self.onGround = False
|
|
19
|
+
self.canJump = False
|
|
20
|
+
|
|
21
|
+
self.sample = 10
|
|
22
|
+
|
|
23
|
+
self.vx, self.vy = 0, 0
|
|
24
|
+
|
|
25
|
+
def update(self):
|
|
26
|
+
self.ckeck_is_on_ground()
|
|
27
|
+
x, y = self.check_collisions()
|
|
28
|
+
if (Global.cam.follow) != (self.player):
|
|
29
|
+
self.player.x = x
|
|
30
|
+
self.player.y = y
|
|
31
|
+
elif (Global.cam.follow) == (self.player):
|
|
32
|
+
dx = -(self.player.x - x)
|
|
33
|
+
dy = -(self.player.y - y)
|
|
34
|
+
Global.cam.move(self.vx, self.vy)
|
|
35
|
+
|
|
36
|
+
|
|
37
|
+
def check_collisions(self):
|
|
38
|
+
x, y = self.player.x + self.vx, self.player.y + self.vy
|
|
39
|
+
|
|
40
|
+
#basic object collisions
|
|
41
|
+
x, y = self.collisionLogic(Global.collisions, x, y)
|
|
42
|
+
x, y = self.tilemap_collisions(x, y)
|
|
43
|
+
|
|
44
|
+
return x, y
|
|
45
|
+
|
|
46
|
+
def collisionLogic(self, collisions, x, y):
|
|
47
|
+
new_rect = pygame.Rect((x, self.player.y), self.player.dim)
|
|
48
|
+
for collision in collisions:
|
|
49
|
+
#pygame.draw.rect(Global.screen, (255, 0, 0), collision, 1)
|
|
50
|
+
if collision.colliderect(new_rect):
|
|
51
|
+
if self.vx > 0:
|
|
52
|
+
x = collision.left - self.player.dim[0]
|
|
53
|
+
elif self.vx < 0:
|
|
54
|
+
x = collision.right
|
|
55
|
+
self.vx = 0
|
|
56
|
+
|
|
57
|
+
# Y-axis collisions
|
|
58
|
+
new_rect = pygame.Rect((x, y), self.player.dim)
|
|
59
|
+
for collision in collisions:
|
|
60
|
+
#pygame.draw.rect(Global.screen, (255, 0, 0), collision, 1)
|
|
61
|
+
if collision.colliderect(new_rect):
|
|
62
|
+
if self.vy > 0: # falling
|
|
63
|
+
y = collision.top - self.player.dim[1]
|
|
64
|
+
self.vy = 0
|
|
65
|
+
elif self.vy < 0: # jumping
|
|
66
|
+
y = collision.bottom
|
|
67
|
+
self.vy = 0
|
|
68
|
+
|
|
69
|
+
return x, y
|
|
70
|
+
|
|
71
|
+
def tilemap_collisions(self, x, y):
|
|
72
|
+
sample = self.sample
|
|
73
|
+
if Global.tilemap is None:
|
|
74
|
+
return x, y
|
|
75
|
+
|
|
76
|
+
#get player reletive tilemap pos
|
|
77
|
+
prect = pygame.Rect(x, y, self.player.dim[0], self.player.dim[1])
|
|
78
|
+
prx, pry = prect.center
|
|
79
|
+
if Global.cam.follow != self.player:
|
|
80
|
+
if Global.cam.x != 0 or Global.cam.y != 0:
|
|
81
|
+
px = int((prx - Global.tilemap.offset[0]) - Global.cam.x)
|
|
82
|
+
py = int((pry - Global.tilemap.offset[1]) - Global.cam.y)
|
|
83
|
+
px = int(px // Global.tilemap.tileDim[0])
|
|
84
|
+
py = int(py // Global.tilemap.tileDim[1])
|
|
85
|
+
else:
|
|
86
|
+
px = int((x - Global.tilemap.offset[0]) / Global.tilemap.tileDim[0])
|
|
87
|
+
py = int((y - Global.tilemap.offset[1]) / Global.tilemap.tileDim[1])
|
|
88
|
+
else:
|
|
89
|
+
if Global.cam.x != 0 or Global.cam.y != 0:
|
|
90
|
+
px = int(((prx + Global.cam.x)-Global.tilemap.offset[0]) // Global.tilemap.tileDim[0])
|
|
91
|
+
py = int(((pry + Global.cam.y)-Global.tilemap.offset[1]) // Global.tilemap.tileDim[1])
|
|
92
|
+
else:
|
|
93
|
+
px = int((x - Global.tilemap.offset[0]) / Global.tilemap.tileDim[0])
|
|
94
|
+
py = int((y - Global.tilemap.offset[1]) / Global.tilemap.tileDim[1])
|
|
95
|
+
|
|
96
|
+
#draw collision rect
|
|
97
|
+
#print(f"px: {px}, py: {py} | cam.x: {Global.cam.x}, cam.y: {Global.cam.y} | x: {x}, y: {y}")
|
|
98
|
+
#rect = pygame.Rect(px , py, self.player.dim[0], self.player.dim[1])
|
|
99
|
+
#pygame.draw.rect(Global.screen, "red", rect)
|
|
100
|
+
#rect.x *= Global.tilemap.tileDim[0]
|
|
101
|
+
#rect.y *= Global.tilemap.tileDim[1]
|
|
102
|
+
#pygame.draw.rect(Global.screen, "yellow", rect, 1)
|
|
103
|
+
#pygame.display.update(rect)
|
|
104
|
+
|
|
105
|
+
#check if player is on tilemap
|
|
106
|
+
if px < 0 or px >= Global.tilemap.mapDim[0] or py < 0 or py >= Global.tilemap.mapDim[1]:
|
|
107
|
+
return x, y
|
|
108
|
+
#get collision rects around player
|
|
109
|
+
collisions: list[pygame.Rect] = []
|
|
110
|
+
for tx in range(px - sample, px + sample):
|
|
111
|
+
for ty in range(py - sample, py + sample):
|
|
112
|
+
nx = int(px + tx)
|
|
113
|
+
ny = int(py + ty)
|
|
114
|
+
#if tile is on map
|
|
115
|
+
if nx < 0 or nx >= Global.tilemap.mapDim[0] or ny < 0 or ny >= Global.tilemap.mapDim[1]:
|
|
116
|
+
continue
|
|
117
|
+
#if tile has defined collision shape
|
|
118
|
+
tile = str(Global.tilemap.map[ny][nx])
|
|
119
|
+
if tile not in Global.tilemap.collisionDict: continue
|
|
120
|
+
|
|
121
|
+
#get collision shape
|
|
122
|
+
rectshape = Global.tilemap.collisionDict[str(tile)]
|
|
123
|
+
rect = getattr(Global.tilemap.collisionShapes, rectshape).copy()
|
|
124
|
+
|
|
125
|
+
# Position rect correctly in the world
|
|
126
|
+
if Global.cam.follow != self.player:
|
|
127
|
+
if Global.cam.x != 0 or Global.cam.y != 0:
|
|
128
|
+
rect.x = ((nx * Global.tilemap.tileDim[0]) + Global.tilemap.offset[0]) - Global.cam.x
|
|
129
|
+
rect.y = ((ny * Global.tilemap.tileDim[1]) + Global.tilemap.offset[1]) - Global.cam.y
|
|
130
|
+
else:
|
|
131
|
+
rect.x += (nx * Global.tilemap.tileDim[0] + Global.tilemap.offset[0]) - Global.cam.x
|
|
132
|
+
rect.y += (ny * Global.tilemap.tileDim[1] + Global.tilemap.offset[1]) - Global.cam.y
|
|
133
|
+
else:
|
|
134
|
+
if Global.cam.x != 0 or Global.cam.y != 0:
|
|
135
|
+
rect.x += ((nx * Global.tilemap.tileDim[0]) + Global.tilemap.offset[0]) - Global.cam.x
|
|
136
|
+
rect.y += ((ny * Global.tilemap.tileDim[1]) + Global.tilemap.offset[1]) - Global.cam.y
|
|
137
|
+
else:
|
|
138
|
+
rect.x += (nx * Global.tilemap.tileDim[0] + Global.tilemap.offset[0]) - Global.cam.x
|
|
139
|
+
rect.y += (ny * Global.tilemap.tileDim[1] + Global.tilemap.offset[1]) - Global.cam.y
|
|
140
|
+
collisions.append(rect)
|
|
141
|
+
|
|
142
|
+
#check collisions
|
|
143
|
+
x, y = self.collisionLogic(collisions, x, y)
|
|
144
|
+
|
|
145
|
+
return x, y
|
|
146
|
+
|
|
147
|
+
|
|
148
|
+
|
|
149
|
+
|
|
150
|
+
def ckeck_is_on_ground(self):
|
|
151
|
+
self.canJump = False
|
|
152
|
+
rect = pygame.Rect(self.player.x, self.player.y + self.player.dim[1], self.player.dim[0], 10)
|
|
153
|
+
for collision in Global.collisions:
|
|
154
|
+
if collision.colliderect(rect):
|
|
155
|
+
self.canJump = True
|
|
156
|
+
|
|
157
|
+
|
|
158
|
+
def move(self, x, y):
|
|
159
|
+
self.vx += x * self.speed
|
|
160
|
+
self.vy += y * self.speed
|
|
161
|
+
|
|
162
|
+
def top_down_movement(self):
|
|
163
|
+
keys = pygame.key.get_pressed()
|
|
164
|
+
if keys[pygame.K_a]:
|
|
165
|
+
self.move(-1, 0)
|
|
166
|
+
if keys[pygame.K_d]:
|
|
167
|
+
self.move(1, 0)
|
|
168
|
+
if keys[pygame.K_w]:
|
|
169
|
+
self.move(0, -1)
|
|
170
|
+
if keys[pygame.K_s]:
|
|
171
|
+
self.move(0, 1)
|
|
172
|
+
#limit velocity
|
|
173
|
+
self.vx = clamp(self.vx, -self.maxV, self.maxV)
|
|
174
|
+
self.vy = clamp(self.vy, -self.maxV, self.maxV)
|
|
175
|
+
self.vx = moveTward(self.vx, 0, self.airRes)
|
|
176
|
+
self.vy = moveTward(self.vy, 0, self.airRes)
|
|
177
|
+
self.vx = zeroOut(self.vx, 0.3)
|
|
178
|
+
self.vy = zeroOut(self.vy, 0.3)
|
|
179
|
+
|
|
180
|
+
def platforming_movement(self):
|
|
181
|
+
keys = pygame.key.get_pressed()
|
|
182
|
+
if keys[pygame.K_a]:
|
|
183
|
+
self.move(-1, 0)
|
|
184
|
+
if keys[pygame.K_d]:
|
|
185
|
+
self.move(1, 0)
|
|
186
|
+
if keys[pygame.K_w] and self.canJump:
|
|
187
|
+
self.vy -= self.jump
|
|
188
|
+
#limit velocity
|
|
189
|
+
self.vx = clamp(self.vx, -self.maxV, self.maxV)
|
|
190
|
+
self.vx = moveTward(self.vx, 0, self.airRes)
|
|
191
|
+
self.vx = zeroOut(self.vx, 0.3)
|
|
192
|
+
if self.player.gravity and not self.onGround: self.vy += self.gravity
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import pygame
|
|
2
|
+
|
|
3
|
+
class _tileCollisionDefs:
|
|
4
|
+
def __init__(self, tileDim):
|
|
5
|
+
width, height = tileDim
|
|
6
|
+
self.full = pygame.Rect(0, 0, width, height)
|
|
7
|
+
|
|
8
|
+
self.halfLeft = pygame.Rect(0, 0, width / 2, height)
|
|
9
|
+
self.halfRight = pygame.Rect(width / 2, 0, width / 2, height)
|
|
10
|
+
self.halfTop = pygame.Rect(0, 0, width, height / 2)
|
|
11
|
+
self.halfBottom = pygame.Rect(0, height / 2, width, height / 2)
|
|
12
|
+
|
|
13
|
+
self.topRight = pygame.Rect(width / 2, 0, width / 2, height / 2)
|
|
14
|
+
self.topLeft = pygame.Rect(0, 0, width / 2, height / 2)
|
|
15
|
+
self.bottomRight = pygame.Rect(width / 2, height / 2, width / 2, height / 2)
|
|
16
|
+
self.bottomLeft = pygame.Rect(0, height / 2, width / 2, height / 2)
|
|
17
|
+
|
|
18
|
+
self.dot = pygame.Rect(0, 0, 3, 3)
|
|
19
|
+
|
|
20
|
+
self.center = pygame.Rect(width / 2, height / 2, width / 2, height / 2)
|
|
21
|
+
|
|
22
|
+
self.none = pygame.Rect(0, 0, 0, 0)
|
|
23
|
+
|
|
24
|
+
def regenerate(self, tileDim):
|
|
25
|
+
width, height = tileDim
|
|
26
|
+
self.full = pygame.Rect(0, 0, width, height)
|
|
27
|
+
|
|
28
|
+
self.halfLeft = pygame.Rect(0, 0, width / 2, height)
|
|
29
|
+
self.halfRight = pygame.Rect(width / 2, 0, width / 2, height)
|
|
30
|
+
self.halfTop = pygame.Rect(0, 0, width, height / 2)
|
|
31
|
+
self.halfBottom = pygame.Rect(0, height / 2, width, height / 2)
|
|
32
|
+
|
|
33
|
+
self.center = pygame.Rect(width / 2, height / 2, width / 2, height / 2)
|
|
34
|
+
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
import pygame
|
|
2
|
+
import numpy as np
|
|
3
|
+
import json
|
|
4
|
+
|
|
5
|
+
from ..basics._net import Global
|
|
6
|
+
|
|
7
|
+
from ._collisionDef import _tileCollisionDefs
|
|
8
|
+
|
|
9
|
+
class TileMap:
|
|
10
|
+
def __init__(self, tileSet: str, tileDim: tuple, tileScale: float, mapDim: tuple, mapFill: int, offset: tuple):
|
|
11
|
+
self.tilesetFile = tileSet
|
|
12
|
+
self.mapFile = None
|
|
13
|
+
self.tileDim = (tileDim[0] * tileScale, tileDim[1] * tileScale)
|
|
14
|
+
self.tileDim = (self.tileDim[0] * Global.cam.scale, self.tileDim[1] * Global.cam.scale)
|
|
15
|
+
self.mapDim = mapDim
|
|
16
|
+
self.offset = offset
|
|
17
|
+
self.tilescale = tileScale
|
|
18
|
+
self.orginDim = tileDim
|
|
19
|
+
|
|
20
|
+
Global.game.objs.append(self)
|
|
21
|
+
Global.tilemap = self
|
|
22
|
+
|
|
23
|
+
self.collisionShapes = _tileCollisionDefs(self.tileDim)
|
|
24
|
+
|
|
25
|
+
self.collisionDict = {}
|
|
26
|
+
|
|
27
|
+
#map, tile splitting, ect
|
|
28
|
+
#--create map
|
|
29
|
+
self.map = np.full(self.mapDim, mapFill)
|
|
30
|
+
#--split map into tiles
|
|
31
|
+
self.tiles = {}
|
|
32
|
+
tileset = pygame.image.load(tileSet).convert_alpha()
|
|
33
|
+
tile_w, tile_h = tileDim
|
|
34
|
+
tile_id = 0
|
|
35
|
+
tileset_w, tileset_h = tileset.get_size()
|
|
36
|
+
|
|
37
|
+
for y in range(0, tileset_h, tile_h):
|
|
38
|
+
for x in range(0, tileset_w, tile_w):
|
|
39
|
+
tile = pygame.Surface(tileDim, pygame.SRCALPHA)
|
|
40
|
+
tile.blit(tileset, (0, 0), (x, y, tile_w, tile_h))
|
|
41
|
+
self.tiles[tile_id] = pygame.transform.scale(tile, self.tileDim)
|
|
42
|
+
tile_id += 1
|
|
43
|
+
|
|
44
|
+
print(f"tiles: {self.tiles}")
|
|
45
|
+
Global.tilmap = self
|
|
46
|
+
|
|
47
|
+
def load_map_from_json(self, filePath: str):
|
|
48
|
+
with open(filePath, "r") as f:
|
|
49
|
+
data = json.load(f)
|
|
50
|
+
self.__private_loadData(filePath, data)
|
|
51
|
+
|
|
52
|
+
def __private_loadData(self, path: str, data: dict):
|
|
53
|
+
self.map = np.array(data["map"])
|
|
54
|
+
self.mapFile = path
|
|
55
|
+
self.collisionDict = data["collisions"]
|
|
56
|
+
|
|
57
|
+
def update(self):
|
|
58
|
+
self.draw_tiles()
|
|
59
|
+
|
|
60
|
+
|
|
61
|
+
def draw_tiles(self):
|
|
62
|
+
for y in range(self.mapDim[1]):
|
|
63
|
+
for x in range(self.mapDim[0]):
|
|
64
|
+
tile = self.tiles[self.map[y][x]]
|
|
65
|
+
mx = (x * self.tileDim[0] + self.offset[0]) - Global.cam.x
|
|
66
|
+
my = (y * self.tileDim[1] + self.offset[1]) - Global.cam.y
|
|
67
|
+
if mx < -self.tileDim[0] or mx > Global.screenDim[0] or my < -self.tileDim[1] or my > Global.screenDim[1]: continue
|
|
68
|
+
Global.screen.blit(tile, (mx, my))
|
|
69
|
+
|
|
70
|
+
def _quit(self):
|
|
71
|
+
#save map
|
|
72
|
+
if self.mapFile is not None:
|
|
73
|
+
print('tilemap saved')
|
|
74
|
+
with open(self.mapFile, "w") as f:
|
|
75
|
+
json.dump(self.map.tolist(), f)
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
from src.GameBox import *
|
|
2
|
+
import pygame
|
|
3
|
+
import os
|
|
4
|
+
|
|
5
|
+
width, height = 800, 600
|
|
6
|
+
game = Game(width, height, "blue", "First Game!")
|
|
7
|
+
win = game.get_screen()
|
|
8
|
+
|
|
9
|
+
Keys.init()
|
|
10
|
+
|
|
11
|
+
cam = Cammera()
|
|
12
|
+
|
|
13
|
+
player = Player((width / 2, height / 4), (50, 50), "green", False)
|
|
14
|
+
player.add_physics(1.0, 3.0, 16, 7.0, 0.5)
|
|
15
|
+
|
|
16
|
+
map = TileMap("tests/levelTiles.png", (16, 16), 5, (25, 25), 10, (0, 0))
|
|
17
|
+
map.load_map_from_json("tests/testMap.json")
|
|
18
|
+
|
|
19
|
+
player.set_tilemap_sample(50)
|
|
20
|
+
|
|
21
|
+
cam.set_follow_target(player)
|
|
22
|
+
#cam.move(-50, -50)
|
|
23
|
+
|
|
24
|
+
running = True
|
|
25
|
+
while running:
|
|
26
|
+
for event in pygame.event.get():
|
|
27
|
+
if event.type == pygame.QUIT:
|
|
28
|
+
running = False
|
|
29
|
+
|
|
30
|
+
player.top_down_movement()
|
|
31
|
+
|
|
32
|
+
game.update(60)
|
|
33
|
+
|
|
34
|
+
|
|
35
|
+
#game.quit()
|
|
36
|
+
pygame.quit()
|
|
Binary file
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
{
|
|
2
|
+
"map": [[3, 3, 3, 3, 7, 7, 7, 3, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7], [7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7], [7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7], [7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7], [7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7], [7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7], [7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7], [7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7], [7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7], [7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7], [7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7], [7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7], [7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7], [7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7], [7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7], [7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7], [7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7], [7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7], [7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7], [7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7], [7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7], [7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7], [7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7], [7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7], [7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7]],
|
|
3
|
+
"collisions": {"7": "none", "3": "halfBottom"}
|
|
4
|
+
}
|
|
@@ -1,23 +0,0 @@
|
|
|
1
|
-
import pygame
|
|
2
|
-
import numpy as np
|
|
3
|
-
|
|
4
|
-
from ..basics._net import Global
|
|
5
|
-
|
|
6
|
-
class Rect:
|
|
7
|
-
def __init__(self, pos: tuple, size: tuple, color: tuple = (0, 0, 0), collision: bool = True):
|
|
8
|
-
self.x, self.y = pos
|
|
9
|
-
self.width, self.height = size
|
|
10
|
-
self.color = color
|
|
11
|
-
Global.game.objs.append(self)
|
|
12
|
-
self.collision = collision
|
|
13
|
-
|
|
14
|
-
def update(self):
|
|
15
|
-
rect = pygame.Rect(self.x - Global.cam.x
|
|
16
|
-
, self.y - Global.cam.y
|
|
17
|
-
, self.width, self.height)
|
|
18
|
-
if self.collision: Global.collisions.append(rect)
|
|
19
|
-
pygame.draw.rect(Global.screen, self.color, rect)
|
|
20
|
-
|
|
21
|
-
def move(self, x, y):
|
|
22
|
-
self.x += x
|
|
23
|
-
self.y += y
|
|
@@ -1,104 +0,0 @@
|
|
|
1
|
-
import pygame
|
|
2
|
-
import numpy as np
|
|
3
|
-
|
|
4
|
-
from ..basics._net import Global
|
|
5
|
-
from ..basics.utils import clamp, moveTward, zeroOut
|
|
6
|
-
|
|
7
|
-
class _playerPhysics:
|
|
8
|
-
def __init__(self, player, speed: float = 1.0, gravity: float = 0.0, jump: float = 0.0, maxV: float = 10.0, airRes: float = 0.2):
|
|
9
|
-
self.player = player
|
|
10
|
-
self.rect = pygame.Rect(self.player.x, self.player.y, self.player.dim[0], self.player.dim[1])
|
|
11
|
-
|
|
12
|
-
self.speed = speed
|
|
13
|
-
self.gravity = gravity
|
|
14
|
-
self.jump = jump
|
|
15
|
-
self.player = player
|
|
16
|
-
self.maxV = maxV
|
|
17
|
-
self.airRes = airRes
|
|
18
|
-
self.onGround = False
|
|
19
|
-
self.canJump = False
|
|
20
|
-
|
|
21
|
-
self.vx, self.vy = 0, 0
|
|
22
|
-
|
|
23
|
-
def update(self):
|
|
24
|
-
self.ckeck_is_on_ground()
|
|
25
|
-
x, y = self.check_collisions()
|
|
26
|
-
if type(Global.cam.follow) != type(self.player):
|
|
27
|
-
self.player.x = x
|
|
28
|
-
self.player.y = y
|
|
29
|
-
elif type(Global.cam.follow) == type(self.player):
|
|
30
|
-
dx = -(self.player.x - x)
|
|
31
|
-
dy = -(self.player.y - y)
|
|
32
|
-
Global.cam.move(self.vx, self.vy)
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
def check_collisions(self):
|
|
37
|
-
x, y = self.player.x + self.vx, self.player.y + self.vy
|
|
38
|
-
|
|
39
|
-
# X-axis collisions
|
|
40
|
-
new_rect = pygame.Rect((x, self.player.y), self.player.dim)
|
|
41
|
-
for collision in Global.collisions:
|
|
42
|
-
if collision.colliderect(new_rect):
|
|
43
|
-
if self.vx > 0:
|
|
44
|
-
x = collision.left - self.player.dim[0]
|
|
45
|
-
elif self.vx < 0:
|
|
46
|
-
x = collision.right
|
|
47
|
-
self.vx = 0
|
|
48
|
-
|
|
49
|
-
# Y-axis collisions
|
|
50
|
-
new_rect = pygame.Rect((x, y), self.player.dim)
|
|
51
|
-
for collision in Global.collisions:
|
|
52
|
-
if collision.colliderect(new_rect):
|
|
53
|
-
if self.vy > 0: # falling
|
|
54
|
-
y = collision.top - self.player.dim[1]
|
|
55
|
-
self.vy = 0
|
|
56
|
-
elif self.vy < 0: # jumping
|
|
57
|
-
y = collision.bottom
|
|
58
|
-
self.vy = 0
|
|
59
|
-
|
|
60
|
-
return x, y
|
|
61
|
-
|
|
62
|
-
def ckeck_is_on_ground(self):
|
|
63
|
-
self.canJump = False
|
|
64
|
-
rect = pygame.Rect(self.player.x, self.player.y + self.player.dim[1], self.player.dim[0], 10)
|
|
65
|
-
for collision in Global.collisions:
|
|
66
|
-
if collision.colliderect(rect):
|
|
67
|
-
self.canJump = True
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
def move(self, x, y):
|
|
71
|
-
self.vx += x * self.speed
|
|
72
|
-
self.vy += y * self.speed
|
|
73
|
-
|
|
74
|
-
def top_down_movement(self):
|
|
75
|
-
keys = pygame.key.get_pressed()
|
|
76
|
-
if keys[pygame.K_a]:
|
|
77
|
-
self.move(-1, 0)
|
|
78
|
-
if keys[pygame.K_d]:
|
|
79
|
-
self.move(1, 0)
|
|
80
|
-
if keys[pygame.K_w]:
|
|
81
|
-
self.move(0, -1)
|
|
82
|
-
if keys[pygame.K_s]:
|
|
83
|
-
self.move(0, 1)
|
|
84
|
-
#limit velocity
|
|
85
|
-
self.vx = clamp(self.vx, -self.maxV, self.maxV)
|
|
86
|
-
self.vy = clamp(self.vy, -self.maxV, self.maxV)
|
|
87
|
-
self.vx = moveTward(self.vx, 0, self.airRes)
|
|
88
|
-
self.vy = moveTward(self.vy, 0, self.airRes)
|
|
89
|
-
self.vx = zeroOut(self.vx, 0.3)
|
|
90
|
-
self.vy = zeroOut(self.vy, 0.3)
|
|
91
|
-
|
|
92
|
-
def platforming_movement(self):
|
|
93
|
-
keys = pygame.key.get_pressed()
|
|
94
|
-
if keys[pygame.K_a]:
|
|
95
|
-
self.move(-1, 0)
|
|
96
|
-
if keys[pygame.K_d]:
|
|
97
|
-
self.move(1, 0)
|
|
98
|
-
if keys[pygame.K_w] and self.canJump:
|
|
99
|
-
self.vy -= self.jump
|
|
100
|
-
#limit velocity
|
|
101
|
-
self.vx = clamp(self.vx, -self.maxV, self.maxV)
|
|
102
|
-
self.vx = moveTward(self.vx, 0, self.airRes)
|
|
103
|
-
self.vx = zeroOut(self.vx, 0.3)
|
|
104
|
-
if self.player.gravity and not self.onGround: self.vy += self.gravity
|
|
@@ -1,31 +0,0 @@
|
|
|
1
|
-
from src.GameBox import *
|
|
2
|
-
import pygame
|
|
3
|
-
|
|
4
|
-
width, height = 1400, 800
|
|
5
|
-
game = Game(width, height, (124, 204, 201))
|
|
6
|
-
|
|
7
|
-
cam = Cammera()
|
|
8
|
-
|
|
9
|
-
player = Player((width / 2, 500), (50, 50), (0, 255, 0), True)
|
|
10
|
-
|
|
11
|
-
player.add_physics(1.0, 3.0, 16, 7.0, 0.5)
|
|
12
|
-
|
|
13
|
-
rect = Rect((0, 700), (width*20, 100), (255, 0, 0), True)
|
|
14
|
-
|
|
15
|
-
cam.set_follow_target(player)
|
|
16
|
-
|
|
17
|
-
running = True
|
|
18
|
-
|
|
19
|
-
while running:
|
|
20
|
-
for event in pygame.event.get():
|
|
21
|
-
if event.type == pygame.QUIT:
|
|
22
|
-
running = False
|
|
23
|
-
|
|
24
|
-
player.platforming_movement()
|
|
25
|
-
|
|
26
|
-
game.update()
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
pygame.quit()
|
|
31
|
-
quit()
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|