GameBox 0.1.2__tar.gz → 0.2.0__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.2.0/.gitignore +12 -0
- {gamebox-0.1.2 → gamebox-0.2.0}/PKG-INFO +3 -1
- {gamebox-0.1.2 → gamebox-0.2.0}/README.md +2 -0
- {gamebox-0.1.2 → gamebox-0.2.0}/pyproject.toml +1 -1
- {gamebox-0.1.2 → gamebox-0.2.0}/src/GameBox/__init__.py +6 -2
- {gamebox-0.1.2 → gamebox-0.2.0}/src/GameBox/_game.py +18 -2
- {gamebox-0.1.2 → gamebox-0.2.0}/src/GameBox/basics/_net.py +3 -0
- {gamebox-0.1.2 → gamebox-0.2.0}/src/GameBox/basics/_shapes.py +3 -1
- {gamebox-0.1.2 → gamebox-0.2.0}/src/GameBox/basics/cammera.py +7 -1
- gamebox-0.2.0/src/GameBox/helpers/_collisions.py +110 -0
- gamebox-0.2.0/src/GameBox/helpers/_input.py +75 -0
- {gamebox-0.1.2 → gamebox-0.2.0}/src/GameBox/player/_player.py +18 -1
- {gamebox-0.1.2 → gamebox-0.2.0}/src/GameBox/player/_playerPhysics.py +6 -26
- gamebox-0.2.0/src/GameBox/tilemap/_Editor.py +101 -0
- gamebox-0.2.0/src/GameBox/tilemap/_collisionDef.py +34 -0
- gamebox-0.2.0/src/GameBox/tilemap/_tilemap.py +92 -0
- gamebox-0.2.0/tests/basicScreen.py +40 -0
- gamebox-0.2.0/tests/levelTiles.png +0 -0
- gamebox-0.2.0/tests/testMap.json +1 -0
- gamebox-0.1.2/tests/basicScreen.py +0 -29
- {gamebox-0.1.2 → gamebox-0.2.0}/LICENSE +0 -0
- {gamebox-0.1.2 → gamebox-0.2.0}/src/GameBox/basics/__init__.py +0 -0
- {gamebox-0.1.2 → gamebox-0.2.0}/src/GameBox/basics/utils.py +0 -0
- {gamebox-0.1.2 → gamebox-0.2.0}/src/GameBox/player/_playerControler.py +0 -0
gamebox-0.2.0/.gitignore
ADDED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: GameBox
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.2.0
|
|
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,12 @@ class Game:
|
|
|
26
27
|
Global.game = self
|
|
27
28
|
self.objs = []
|
|
28
29
|
|
|
29
|
-
|
|
30
|
+
|
|
31
|
+
def update(self, event: pygame.event,frame_rate=60):
|
|
32
|
+
Global.event = event
|
|
33
|
+
#clear collisions
|
|
30
34
|
Global.collisions.clear()
|
|
35
|
+
|
|
31
36
|
Global.dt = Global.clock.tick(frame_rate) / 1000.0
|
|
32
37
|
Global.screen.fill(Global.bgColor)
|
|
33
38
|
player = None
|
|
@@ -36,3 +41,14 @@ class Game:
|
|
|
36
41
|
else: obj.update()
|
|
37
42
|
if player != None: player.update()
|
|
38
43
|
pygame.display.update()
|
|
44
|
+
|
|
45
|
+
def get_screen(self):
|
|
46
|
+
return Global.screen
|
|
47
|
+
|
|
48
|
+
def quit(self):
|
|
49
|
+
#will save files later
|
|
50
|
+
for obj in self.objs:
|
|
51
|
+
if hasattr(obj, "_quit") and callable(obj._quit):
|
|
52
|
+
obj._quit()
|
|
53
|
+
|
|
54
|
+
|
|
@@ -14,15 +14,18 @@ class _global_:
|
|
|
14
14
|
#--game and cam
|
|
15
15
|
self.game: object = None
|
|
16
16
|
self.cam: object = None
|
|
17
|
+
self.event: pygame.event = None
|
|
17
18
|
#-collisions
|
|
18
19
|
self.collisions: list[pygame.Rect] = []
|
|
19
20
|
|
|
20
21
|
#objects
|
|
21
22
|
self.player = self._player()
|
|
23
|
+
self.tilemap = []
|
|
22
24
|
|
|
23
25
|
class _player:
|
|
24
26
|
def __init__(self):
|
|
25
27
|
self.pos: tuple = None
|
|
28
|
+
self.player: object = None
|
|
26
29
|
|
|
27
30
|
|
|
28
31
|
|
|
@@ -12,6 +12,8 @@ class Rect:
|
|
|
12
12
|
self.collision = collision
|
|
13
13
|
|
|
14
14
|
def update(self):
|
|
15
|
+
width = self.width * Global.cam.scale
|
|
16
|
+
height = self.height * Global.cam.scale
|
|
15
17
|
if (Global.cam.follow) != (self):
|
|
16
18
|
x = self.x - Global.cam.x
|
|
17
19
|
y = self.y - Global.cam.y
|
|
@@ -19,7 +21,7 @@ class Rect:
|
|
|
19
21
|
x = self.x
|
|
20
22
|
y = self.y
|
|
21
23
|
|
|
22
|
-
rect = pygame.Rect(x, y,
|
|
24
|
+
rect = pygame.Rect(x, y, width ,height)
|
|
23
25
|
if self.collision: Global.collisions.append(rect)
|
|
24
26
|
pygame.draw.rect(Global.screen, self.color, rect)
|
|
25
27
|
|
|
@@ -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,110 @@
|
|
|
1
|
+
import pygame
|
|
2
|
+
import numpy as np
|
|
3
|
+
|
|
4
|
+
from ..basics._net import Global
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
def CheckCollisions(x, y, vx, vy, dim, sample, obj):
|
|
8
|
+
x, y = x + vx, y + vy
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
#basic object collisions
|
|
12
|
+
x, y, vx, vy = _mainCollisionLogic(Global.collisions, x, y, vx, vy, dim)
|
|
13
|
+
x, y, vx, vy = _checkTilemapCollisions(x, y, vx, vy, dim, sample, obj)
|
|
14
|
+
|
|
15
|
+
return x, y, vx, vy
|
|
16
|
+
|
|
17
|
+
def _mainCollisionLogic(collisions, x, y, vx, vy, dim):
|
|
18
|
+
new_rect = pygame.Rect((x, y), dim)
|
|
19
|
+
for collision in collisions:
|
|
20
|
+
#pygame.draw.rect(Global.screen, (255, 0, 0), collision, 1)
|
|
21
|
+
if collision.colliderect(new_rect):
|
|
22
|
+
if vx > 0:
|
|
23
|
+
x = collision.left - dim[0]
|
|
24
|
+
elif vx < 0:
|
|
25
|
+
x = collision.right
|
|
26
|
+
vx = 0
|
|
27
|
+
|
|
28
|
+
# Y-axis collisions
|
|
29
|
+
new_rect = pygame.Rect((x, y), dim)
|
|
30
|
+
for collision in collisions:
|
|
31
|
+
#pygame.draw.rect(Global.screen, (255, 0, 0), collision, 1)
|
|
32
|
+
if collision.colliderect(new_rect):
|
|
33
|
+
if vy > 0: # falling
|
|
34
|
+
y = collision.top - dim[1]
|
|
35
|
+
vy = 0
|
|
36
|
+
elif vy < 0: # jumping
|
|
37
|
+
y = collision.bottom
|
|
38
|
+
vy = 0
|
|
39
|
+
|
|
40
|
+
return x, y, vx, vy
|
|
41
|
+
|
|
42
|
+
def _checkTilemapCollisions(x, y, vx, vy, dim, sample, obj):
|
|
43
|
+
if len(Global.tilemap) == 0:
|
|
44
|
+
return x, y, vx, vy
|
|
45
|
+
|
|
46
|
+
for tilemap in Global.tilemap:
|
|
47
|
+
|
|
48
|
+
#get player reletive tilemap pos
|
|
49
|
+
prect = pygame.Rect(x, y, dim[0], dim[1])
|
|
50
|
+
prx, pry = prect.center
|
|
51
|
+
if Global.cam.follow != obj:
|
|
52
|
+
if Global.cam.x != 0 or Global.cam.y != 0:
|
|
53
|
+
px = int((prx) - Global.cam.x)
|
|
54
|
+
py = int((pry) - Global.cam.y)
|
|
55
|
+
px = int(px // tilemap.tileDim[0])
|
|
56
|
+
py = int(py // tilemap.tileDim[1])
|
|
57
|
+
else:
|
|
58
|
+
px = int((x) / tilemap.tileDim[0])
|
|
59
|
+
py = int((y ) / tilemap.tileDim[1])
|
|
60
|
+
else:
|
|
61
|
+
if Global.cam.x != 0 or Global.cam.y != 0:
|
|
62
|
+
px = int(((prx + Global.cam.x)) // tilemap.tileDim[0])
|
|
63
|
+
py = int(((pry + Global.cam.y)) // tilemap.tileDim[1])
|
|
64
|
+
else:
|
|
65
|
+
px = int((x) / tilemap.tileDim[0])
|
|
66
|
+
py = int((y) / tilemap.tileDim[1])
|
|
67
|
+
|
|
68
|
+
|
|
69
|
+
#check if player is on tilemap
|
|
70
|
+
if px < 0 or px >= tilemap.mapDim[0] or py < 0 or py >= tilemap.mapDim[1]:
|
|
71
|
+
return x, y, vx, vy
|
|
72
|
+
#get collision rects around player
|
|
73
|
+
collisions: list[pygame.Rect] = []
|
|
74
|
+
for tx in range(px - sample, px + sample):
|
|
75
|
+
for ty in range(py - sample, py + sample):
|
|
76
|
+
nx = int(px + tx)
|
|
77
|
+
ny = int(py + ty)
|
|
78
|
+
#if tile is on map
|
|
79
|
+
if nx < 0 or nx >= tilemap.mapDim[0] or ny < 0 or ny >= tilemap.mapDim[1]:
|
|
80
|
+
continue
|
|
81
|
+
#if tile has defined collision shape
|
|
82
|
+
tile = str(tilemap.map[ny][nx])
|
|
83
|
+
if tile not in tilemap.collisionDict: continue
|
|
84
|
+
|
|
85
|
+
#get collision shape
|
|
86
|
+
rectshape = tilemap.collisionDict[str(tile)]
|
|
87
|
+
rect = getattr(tilemap.collisionShapes, rectshape).copy()
|
|
88
|
+
|
|
89
|
+
# Position rect correctly in the world
|
|
90
|
+
if Global.cam.follow != obj:
|
|
91
|
+
if Global.cam.x != 0 or Global.cam.y != 0:
|
|
92
|
+
rect.x = ((nx * tilemap.tileDim[0])) - Global.cam.x
|
|
93
|
+
rect.y = ((ny * tilemap.tileDim[1])) - Global.cam.y
|
|
94
|
+
else:
|
|
95
|
+
rect.x += (nx * tilemap.tileDim[0]) - Global.cam.x
|
|
96
|
+
rect.y += (ny * tilemap.tileDim[1]) - Global.cam.y
|
|
97
|
+
else:
|
|
98
|
+
if Global.cam.x != 0 or Global.cam.y != 0:
|
|
99
|
+
rect.x += ((nx * tilemap.tileDim[0])) - Global.cam.x
|
|
100
|
+
rect.y += ((ny * tilemap.tileDim[1])) - Global.cam.y
|
|
101
|
+
else:
|
|
102
|
+
rect.x += (nx * tilemap.tileDim[0]) - Global.cam.x
|
|
103
|
+
rect.y += (ny * tilemap.tileDim[1]) - Global.cam.y
|
|
104
|
+
collisions.append(rect)
|
|
105
|
+
|
|
106
|
+
#check collisions
|
|
107
|
+
x, y, vx, vy = _mainCollisionLogic(collisions, x, y, vx, vy, dim)
|
|
108
|
+
|
|
109
|
+
return x, y, vx, vy
|
|
110
|
+
|
|
@@ -0,0 +1,75 @@
|
|
|
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
|
+
self.tab = pygame.K_TAB
|
|
55
|
+
|
|
56
|
+
#arrow keys
|
|
57
|
+
self.up = pygame.K_UP
|
|
58
|
+
self.down = pygame.K_DOWN
|
|
59
|
+
self.left = pygame.K_LEFT
|
|
60
|
+
self.right = pygame.K_RIGHT
|
|
61
|
+
|
|
62
|
+
#mouse
|
|
63
|
+
self.mouse_x, self.mouse_y = 0, 0
|
|
64
|
+
def init(self): Global.game.objs.append(self)
|
|
65
|
+
|
|
66
|
+
def is_pressed(self, key):
|
|
67
|
+
for event in Global.event:
|
|
68
|
+
if event.type == pygame.KEYDOWN:
|
|
69
|
+
if event.key == key: return True
|
|
70
|
+
return False
|
|
71
|
+
|
|
72
|
+
def update(self): self.mouse_x, self.mouse_y = pygame.mouse.get_pos()
|
|
73
|
+
|
|
74
|
+
|
|
75
|
+
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,7 +25,15 @@ class Player:
|
|
|
24
25
|
def update(self):
|
|
25
26
|
self.physics.update()
|
|
26
27
|
#debug rect
|
|
27
|
-
|
|
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)
|
|
28
37
|
pygame.draw.rect(Global.screen, self.color, rect)
|
|
29
38
|
|
|
30
39
|
#movement
|
|
@@ -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
|
|
@@ -3,6 +3,7 @@ import numpy as np
|
|
|
3
3
|
|
|
4
4
|
from ..basics._net import Global
|
|
5
5
|
from ..basics.utils import clamp, moveTward, zeroOut
|
|
6
|
+
from ..helpers._collisions import CheckCollisions
|
|
6
7
|
|
|
7
8
|
class _playerPhysics:
|
|
8
9
|
def __init__(self, player, speed: float = 1.0, gravity: float = 0.0, jump: float = 0.0, maxV: float = 10.0, airRes: float = 0.2):
|
|
@@ -18,11 +19,15 @@ class _playerPhysics:
|
|
|
18
19
|
self.onGround = False
|
|
19
20
|
self.canJump = False
|
|
20
21
|
|
|
22
|
+
self.sample = 10
|
|
23
|
+
|
|
21
24
|
self.vx, self.vy = 0, 0
|
|
22
25
|
|
|
23
26
|
def update(self):
|
|
24
27
|
self.ckeck_is_on_ground()
|
|
25
|
-
x, y = self.
|
|
28
|
+
x, y, self.vx, self.vy = CheckCollisions(self.player.x, self.player.y,
|
|
29
|
+
self.vx, self.vy, self.player.dim,
|
|
30
|
+
self.sample,self.player)
|
|
26
31
|
if (Global.cam.follow) != (self.player):
|
|
27
32
|
self.player.x = x
|
|
28
33
|
self.player.y = y
|
|
@@ -30,34 +35,9 @@ class _playerPhysics:
|
|
|
30
35
|
dx = -(self.player.x - x)
|
|
31
36
|
dy = -(self.player.y - y)
|
|
32
37
|
Global.cam.move(self.vx, self.vy)
|
|
33
|
-
|
|
34
|
-
|
|
35
38
|
|
|
36
|
-
def check_collisions(self):
|
|
37
|
-
x, y = self.player.x + self.vx, self.player.y + self.vy
|
|
38
39
|
|
|
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
40
|
|
|
60
|
-
return x, y
|
|
61
41
|
|
|
62
42
|
def ckeck_is_on_ground(self):
|
|
63
43
|
self.canJump = False
|
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
import pygame
|
|
2
|
+
import numpy as np
|
|
3
|
+
|
|
4
|
+
from..helpers._input import Keys
|
|
5
|
+
from ..basics._net import Global
|
|
6
|
+
|
|
7
|
+
class _tilemapEditor:
|
|
8
|
+
def __init__(self, tilemap, activation):
|
|
9
|
+
self.tilemap = tilemap
|
|
10
|
+
self.activation = activation
|
|
11
|
+
self.active = False
|
|
12
|
+
|
|
13
|
+
self.selectedTile = 1
|
|
14
|
+
self.mx, self.my = Keys.mouse_x, Keys.mouse_y
|
|
15
|
+
|
|
16
|
+
self.mode = "paint"
|
|
17
|
+
|
|
18
|
+
def _update(self):
|
|
19
|
+
if self.active:
|
|
20
|
+
#update mouse pos
|
|
21
|
+
self.mx, self.my = Keys.mouse_x, Keys.mouse_y
|
|
22
|
+
self.mx += Global.cam.x
|
|
23
|
+
self.my += Global.cam.y
|
|
24
|
+
self.mx = self.mx // self.tilemap.tileDim[0] * self.tilemap.tileDim[0]
|
|
25
|
+
self.my = self.my // self.tilemap.tileDim[1] * self.tilemap.tileDim[1]
|
|
26
|
+
|
|
27
|
+
self._mode_()
|
|
28
|
+
self.moveSelectionByArrowKeys()
|
|
29
|
+
self.ui()
|
|
30
|
+
|
|
31
|
+
#toggle
|
|
32
|
+
if Keys.is_pressed(self.activation): self.active = not self.active
|
|
33
|
+
|
|
34
|
+
def _mode_(self):
|
|
35
|
+
x, y = Keys.mouse_x, Keys.mouse_y
|
|
36
|
+
if x > self.tilemap.tileset.get_size()[0] * self.tilemap.tilescale / 2 or y > self.tilemap.tileset.get_size()[1] * self.tilemap.tilescale / 2:
|
|
37
|
+
self.mode = "paint"
|
|
38
|
+
#more parrimeters will be placed as needed
|
|
39
|
+
else:
|
|
40
|
+
self.mode = "select"
|
|
41
|
+
|
|
42
|
+
def ui(self):
|
|
43
|
+
tile = self.tilemap.tiles[self.selectedTile]
|
|
44
|
+
image = pygame.transform.scale_by(self.tilemap.tileset, self.tilemap.tilescale / 2)
|
|
45
|
+
Global.screen.blit(image, (0, 0))
|
|
46
|
+
#show outlined sellected tile
|
|
47
|
+
x, y = self.tilemap.tilePosInImage[self.selectedTile]
|
|
48
|
+
x *= self.tilemap.tilescale / 2
|
|
49
|
+
y *= self.tilemap.tilescale / 2
|
|
50
|
+
width = self.tilemap.orginDim[0] * self.tilemap.tilescale / 2
|
|
51
|
+
height = self.tilemap.orginDim[1] * self.tilemap.tilescale / 2
|
|
52
|
+
outline = pygame.Rect(x, y, width, height)
|
|
53
|
+
pygame.draw.rect(Global.screen, "white", outline, 2)
|
|
54
|
+
#other stuff
|
|
55
|
+
if self.mode == "paint":
|
|
56
|
+
#show selected tile
|
|
57
|
+
#--outline on tileset
|
|
58
|
+
#--show beside mouse
|
|
59
|
+
x = self.mx
|
|
60
|
+
y = self.my
|
|
61
|
+
|
|
62
|
+
x -= Global.cam.x
|
|
63
|
+
y -= Global.cam.y
|
|
64
|
+
Global.screen.blit(tile, (x, y))
|
|
65
|
+
if pygame.mouse.get_pressed()[0]:
|
|
66
|
+
#check if mouse is on tilemap
|
|
67
|
+
x, y = self.mx // self.tilemap.tileDim[0], self.my // self.tilemap.tileDim[1]
|
|
68
|
+
if x >= 0 and x < self.tilemap.mapDim[0] and y >= 0 and y < self.tilemap.mapDim[1]:
|
|
69
|
+
self.tilemap.map[int(y)][int(x)] = self.selectedTile
|
|
70
|
+
if pygame.mouse.get_pressed()[2]:
|
|
71
|
+
x, y = self.mx // self.tilemap.tileDim[0], self.my // self.tilemap.tileDim[1]
|
|
72
|
+
if x >= 0 and x < self.tilemap.mapDim[0] and y >= 0 and y < self.tilemap.mapDim[1]:
|
|
73
|
+
self.tilemap.map[int(y)][int(x)] = 0
|
|
74
|
+
elif self.mode == "select":
|
|
75
|
+
#paint mouse hovered tile
|
|
76
|
+
x, y = Keys.mouse_x, Keys.mouse_y
|
|
77
|
+
x = (x // width)
|
|
78
|
+
y = (y // height)
|
|
79
|
+
outline = pygame.Rect(x * width, y * width, width, height)
|
|
80
|
+
pygame.draw.rect(Global.screen, "black", outline, 2)
|
|
81
|
+
if pygame.mouse.get_pressed()[0]:
|
|
82
|
+
x *= self.tilemap.orginDim[0]
|
|
83
|
+
y *= self.tilemap.orginDim[1]
|
|
84
|
+
self.selectedTile = self.tilemap.posToTile[(int(x), int(y))]
|
|
85
|
+
|
|
86
|
+
|
|
87
|
+
def moveSelectionByArrowKeys(self):
|
|
88
|
+
x, y = self.tilemap.tilePosInImage[self.selectedTile]
|
|
89
|
+
|
|
90
|
+
width = 16
|
|
91
|
+
height = 16
|
|
92
|
+
|
|
93
|
+
if Keys.is_pressed(Keys.left): x -= width
|
|
94
|
+
if Keys.is_pressed(Keys.right): x += width
|
|
95
|
+
if Keys.is_pressed(Keys.up): y -= height
|
|
96
|
+
if Keys.is_pressed(Keys.down): y += height
|
|
97
|
+
|
|
98
|
+
if (int(x), int(y)) in self.tilemap.posToTile:
|
|
99
|
+
self.selectedTile = self.tilemap.posToTile[(int(x), int(y))]
|
|
100
|
+
|
|
101
|
+
|
|
@@ -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,92 @@
|
|
|
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
|
+
from ._Editor import _tilemapEditor
|
|
9
|
+
|
|
10
|
+
class TileMap:
|
|
11
|
+
def __init__(self, tileSet: str, tileDim: tuple, tileScale: float, mapDim: tuple, mapFill: int, saveFile = None):
|
|
12
|
+
self.tilesetFile = tileSet
|
|
13
|
+
self.mapFile = saveFile
|
|
14
|
+
self.tileDim = (tileDim[0] * tileScale, tileDim[1] * tileScale)
|
|
15
|
+
self.tileDim = (self.tileDim[0] * Global.cam.scale, self.tileDim[1] * Global.cam.scale)
|
|
16
|
+
self.mapDim = mapDim
|
|
17
|
+
self.tilescale = tileScale
|
|
18
|
+
self.orginDim = tileDim
|
|
19
|
+
|
|
20
|
+
self.editor = None
|
|
21
|
+
|
|
22
|
+
Global.game.objs.append(self)
|
|
23
|
+
|
|
24
|
+
self.collisionShapes = _tileCollisionDefs(self.tileDim)
|
|
25
|
+
|
|
26
|
+
self.collisionDict = {}
|
|
27
|
+
|
|
28
|
+
self.tilePosInImage = {}
|
|
29
|
+
self.posToTile = {}
|
|
30
|
+
|
|
31
|
+
#map, tile splitting, ect
|
|
32
|
+
#--create map
|
|
33
|
+
self.map = np.full(self.mapDim, mapFill)
|
|
34
|
+
#--split map into tiles
|
|
35
|
+
self.tiles = {}
|
|
36
|
+
tileset = pygame.image.load(tileSet).convert_alpha()
|
|
37
|
+
self.tileset = tileset
|
|
38
|
+
tile_w, tile_h = tileDim
|
|
39
|
+
tile_id = 1
|
|
40
|
+
tileset_w, tileset_h = tileset.get_size()
|
|
41
|
+
|
|
42
|
+
for y in range(0, tileset_h, tile_h):
|
|
43
|
+
for x in range(0, tileset_w, tile_w):
|
|
44
|
+
tile = pygame.Surface(tileDim, pygame.SRCALPHA)
|
|
45
|
+
tile.blit(tileset, (0, 0), (x, y, tile_w, tile_h))
|
|
46
|
+
self.tiles[tile_id] = pygame.transform.scale(tile, self.tileDim)
|
|
47
|
+
self.tilePosInImage[tile_id] = (x, y)
|
|
48
|
+
self.posToTile[(x, y)] = tile_id
|
|
49
|
+
tile_id += 1
|
|
50
|
+
|
|
51
|
+
Global.tilemap.append(self)
|
|
52
|
+
print(self.posToTile)
|
|
53
|
+
|
|
54
|
+
def load_map_from_json(self, filePath: str):
|
|
55
|
+
with open(filePath, "r") as f:
|
|
56
|
+
data = json.load(f)
|
|
57
|
+
self.__private_loadData(filePath, data)
|
|
58
|
+
|
|
59
|
+
def __private_loadData(self, path: str, data: dict):
|
|
60
|
+
self.map = np.array(data["map"])
|
|
61
|
+
self.mapFile = path
|
|
62
|
+
self.collisionDict = data["collisions"]
|
|
63
|
+
|
|
64
|
+
def activate_editor(self, activation):
|
|
65
|
+
print(f"editor activated. press {activation} to toggle")
|
|
66
|
+
self.editor = _tilemapEditor(self, activation)
|
|
67
|
+
|
|
68
|
+
def update(self):
|
|
69
|
+
self.draw_tiles()
|
|
70
|
+
if self.editor is not None: self.editor._update()
|
|
71
|
+
|
|
72
|
+
|
|
73
|
+
def draw_tiles(self):
|
|
74
|
+
for y in range(self.mapDim[1]):
|
|
75
|
+
for x in range(self.mapDim[0]):
|
|
76
|
+
if self.map[y][x] == 0:
|
|
77
|
+
continue
|
|
78
|
+
tile = self.tiles[self.map[y][x]]
|
|
79
|
+
mx = (x * self.tileDim[0]) - Global.cam.x
|
|
80
|
+
my = (y * self.tileDim[1]) - Global.cam.y
|
|
81
|
+
if mx < -self.tileDim[0] or mx > Global.screenDim[0] or my < -self.tileDim[1] or my > Global.screenDim[1]: continue
|
|
82
|
+
Global.screen.blit(tile, (mx, my))
|
|
83
|
+
|
|
84
|
+
def _quit(self):
|
|
85
|
+
#save map
|
|
86
|
+
if self.mapFile is not None:
|
|
87
|
+
print('tilemap saved')
|
|
88
|
+
with open(self.mapFile, "w") as f:
|
|
89
|
+
data = {}
|
|
90
|
+
data["map"] = self.map.tolist()
|
|
91
|
+
data["collisions"] = self.collisionDict
|
|
92
|
+
json.dump(data, f)
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
from src.GameBox import *
|
|
2
|
+
import pygame
|
|
3
|
+
import os
|
|
4
|
+
|
|
5
|
+
width, height = 1400, 900
|
|
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), 0)
|
|
17
|
+
map.load_map_from_json("tests/testMap.json")
|
|
18
|
+
map.activate_editor(Keys.tab)
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
player.set_tilemap_sample(50)
|
|
23
|
+
|
|
24
|
+
cam.set_follow_target(player)
|
|
25
|
+
#cam.move(-50, -50)
|
|
26
|
+
|
|
27
|
+
running = True
|
|
28
|
+
while running:
|
|
29
|
+
events = pygame.event.get()
|
|
30
|
+
for event in events:
|
|
31
|
+
if event.type == pygame.QUIT:
|
|
32
|
+
running = False
|
|
33
|
+
|
|
34
|
+
player.top_down_movement()
|
|
35
|
+
|
|
36
|
+
game.update(events, 60)
|
|
37
|
+
|
|
38
|
+
os.system("cls")
|
|
39
|
+
game.quit()
|
|
40
|
+
pygame.quit()
|
|
Binary file
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"map": [[11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8], [11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8], [11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8], [11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8], [11, 11, 11, 1, 2, 2, 2, 2, 3, 11, 11, 11, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8], [11, 11, 11, 7, 8, 8, 8, 8, 9, 11, 11, 11, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8], [11, 11, 11, 7, 8, 8, 8, 8, 9, 11, 11, 11, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8], [11, 11, 11, 7, 8, 8, 8, 8, 9, 11, 11, 11, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8], [11, 11, 11, 7, 8, 8, 8, 8, 9, 11, 11, 11, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8], [11, 11, 11, 13, 14, 14, 14, 14, 15, 11, 11, 11, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8], [11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8], [11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8], [11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8], [11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8], [8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 11, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8], [8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8], [8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8], [8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8], [8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8], [8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8], [8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8], [8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8], [8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8], [8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8], [8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8]], "collisions": {}}
|
|
@@ -1,29 +0,0 @@
|
|
|
1
|
-
from src.GameBox import *
|
|
2
|
-
import pygame
|
|
3
|
-
|
|
4
|
-
width, height = 800, 600
|
|
5
|
-
win = Game(width, height, "blue", "First Game!")
|
|
6
|
-
|
|
7
|
-
cam = Cammera()
|
|
8
|
-
|
|
9
|
-
player = Player((width / 2, 375), (50, 50), "green", True)
|
|
10
|
-
player.add_physics(1.0, 3.0, 16, 7.0, 0.5)
|
|
11
|
-
|
|
12
|
-
floor = Rect((0, height-50), (width, 50), "yellow", True)
|
|
13
|
-
|
|
14
|
-
rect = Rect((0, 0), (50, 50), "red", True)
|
|
15
|
-
|
|
16
|
-
cam.set_follow_target(floor)
|
|
17
|
-
|
|
18
|
-
running = True
|
|
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
|
-
floor.move(-0.5, -0.5)
|
|
26
|
-
|
|
27
|
-
win.update(60)
|
|
28
|
-
|
|
29
|
-
pygame.quit()
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|