GameBox 0.9.2__tar.gz → 0.10.0.dev1__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.9.2 → gamebox-0.10.0.dev1}/PKG-INFO +1 -1
- {gamebox-0.9.2 → gamebox-0.10.0.dev1}/pyproject.toml +1 -1
- gamebox-0.10.0.dev1/src/GameBox/Game.py +68 -0
- gamebox-0.10.0.dev1/src/GameBox/__init__.py +39 -0
- gamebox-0.10.0.dev1/src/GameBox/basics/Cammera.py +43 -0
- gamebox-0.10.0.dev1/src/GameBox/basics/Net.py +28 -0
- gamebox-0.10.0.dev1/src/GameBox/basics/Shapes.py +80 -0
- gamebox-0.10.0.dev1/src/GameBox/basics/sound.py +16 -0
- gamebox-0.10.0.dev1/src/GameBox/basics/ui.py +70 -0
- {gamebox-0.9.2 → gamebox-0.10.0.dev1}/src/GameBox/basics/utils.py +2 -1
- gamebox-0.9.2/src/GameBox/helpers/_input.py → gamebox-0.10.0.dev1/src/GameBox/helpers/Input.py +8 -3
- gamebox-0.10.0.dev1/src/GameBox/helpers/_collisions.py +78 -0
- gamebox-0.10.0.dev1/src/GameBox/player/Player.py +45 -0
- gamebox-0.10.0.dev1/src/GameBox/player/_playerControler.py +29 -0
- gamebox-0.10.0.dev1/src/GameBox/player/_playerPhysics.py +35 -0
- gamebox-0.10.0.dev1/src/GameBox/tilemap/Tilemap.py +46 -0
- gamebox-0.10.0.dev1/tests/GettingStarted.py +54 -0
- gamebox-0.10.0.dev1/tests/ObjJoining.py +37 -0
- gamebox-0.10.0.dev1/tests/Platformor.py +29 -0
- gamebox-0.9.2/src/GameBox/GameLevel_ui/_Animations.py +0 -39
- gamebox-0.9.2/src/GameBox/GameLevel_ui/_sprites.py +0 -185
- gamebox-0.9.2/src/GameBox/__init__.py +0 -42
- gamebox-0.9.2/src/GameBox/_game.py +0 -81
- gamebox-0.9.2/src/GameBox/basics/__init__.py +0 -0
- gamebox-0.9.2/src/GameBox/basics/_net.py +0 -36
- gamebox-0.9.2/src/GameBox/basics/_shapes.py +0 -44
- gamebox-0.9.2/src/GameBox/basics/cammera.py +0 -36
- gamebox-0.9.2/src/GameBox/helpers/_Conditions.py +0 -56
- gamebox-0.9.2/src/GameBox/helpers/_collisions.py +0 -165
- gamebox-0.9.2/src/GameBox/player/_player.py +0 -61
- gamebox-0.9.2/src/GameBox/player/_playerControler.py +0 -54
- gamebox-0.9.2/src/GameBox/player/_playerPhysics.py +0 -84
- gamebox-0.9.2/src/GameBox/player/_playerSprite.py +0 -86
- gamebox-0.9.2/src/GameBox/tilemap/_Editor.py +0 -36
- gamebox-0.9.2/src/GameBox/tilemap/_collisionDef.py +0 -41
- gamebox-0.9.2/src/GameBox/tilemap/_editorBrushes.py +0 -166
- gamebox-0.9.2/src/GameBox/tilemap/_tilemap.py +0 -94
- gamebox-0.9.2/src/GameBox/ui/_basicUI.py +0 -36
- gamebox-0.9.2/tests/GettingStarted.py +0 -55
- gamebox-0.9.2/tests/Player.png +0 -0
- gamebox-0.9.2/tests/basicScreen.py +0 -42
- gamebox-0.9.2/tests/testMap.json +0 -1
- {gamebox-0.9.2 → gamebox-0.10.0.dev1}/.gitignore +0 -0
- {gamebox-0.9.2 → gamebox-0.10.0.dev1}/LICENSE +0 -0
- {gamebox-0.9.2 → gamebox-0.10.0.dev1}/README.md +0 -0
- {gamebox-0.9.2/tests → gamebox-0.10.0.dev1/tests/assets}/levelTiles.png +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: GameBox
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.10.0.dev1
|
|
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
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
import pygame
|
|
2
|
+
|
|
3
|
+
from .basics.Net import Global
|
|
4
|
+
from .basics.Shapes import Rect
|
|
5
|
+
|
|
6
|
+
class Game:
|
|
7
|
+
def __init__(self, width: int, height: int, bg_color = "black", title = "Game", resizable: bool = False):
|
|
8
|
+
pygame.init()
|
|
9
|
+
flags = pygame.RESIZABLE if resizable else 0
|
|
10
|
+
self.flags = flags
|
|
11
|
+
self.screen = pygame.Surface((width, height))
|
|
12
|
+
self.width, self.height = width, height
|
|
13
|
+
self.display = pygame.display.set_mode((width, height), flags)
|
|
14
|
+
self.clock = pygame.time.Clock()
|
|
15
|
+
self.running = True
|
|
16
|
+
self.bg_color = bg_color
|
|
17
|
+
self.title = title
|
|
18
|
+
|
|
19
|
+
#set global
|
|
20
|
+
Global.screen = self.screen
|
|
21
|
+
Global.screenDim = pygame.Vector2(width, height)
|
|
22
|
+
Global.bg_color = bg_color
|
|
23
|
+
Global.winTitle = title
|
|
24
|
+
Global.clock = self.clock
|
|
25
|
+
|
|
26
|
+
def update(self, events, render = True, fps=60):
|
|
27
|
+
Global.collision = []
|
|
28
|
+
#update cam
|
|
29
|
+
Global.cam.update()
|
|
30
|
+
|
|
31
|
+
self.screen.fill(Global.bg_color)
|
|
32
|
+
Global.events = events
|
|
33
|
+
Global.dt = self.clock.tick(fps)/1000.0
|
|
34
|
+
|
|
35
|
+
#collect all collision rects first
|
|
36
|
+
for key in range(5, -1, -1):
|
|
37
|
+
for obj in Global.objs[str(key)]:
|
|
38
|
+
if hasattr(obj, '_addCollision'):
|
|
39
|
+
obj._addCollision()
|
|
40
|
+
|
|
41
|
+
#then update all objects
|
|
42
|
+
for key in range(5, -1, -1):
|
|
43
|
+
for obj in Global.objs[str(key)]:
|
|
44
|
+
if hasattr(obj, 'update'):
|
|
45
|
+
obj.update()
|
|
46
|
+
|
|
47
|
+
if render:
|
|
48
|
+
self.display.blit(pygame.transform.scale(self.screen, (self.width, self.height)), (0, 0))
|
|
49
|
+
pygame.display.update()
|
|
50
|
+
|
|
51
|
+
def get_screen(self): return self.screen
|
|
52
|
+
|
|
53
|
+
def rescale(self, event):
|
|
54
|
+
self.width = event.w
|
|
55
|
+
self.height = event.h
|
|
56
|
+
self.display = pygame.display.set_mode((self.width, self.height), self.flags)
|
|
57
|
+
|
|
58
|
+
def quit(self):
|
|
59
|
+
return
|
|
60
|
+
#for tilemap in Global.tilemaps:
|
|
61
|
+
# tilemap._quit()
|
|
62
|
+
|
|
63
|
+
def generate_bounds(self, width, height, color="black", show=False):
|
|
64
|
+
Rect(pygame.Vector2(0, -10), pygame.Vector2(width, 10), color, show)
|
|
65
|
+
Rect(pygame.Vector2(-10, 0), pygame.Vector2(10, height), color, show)
|
|
66
|
+
Rect(pygame.Vector2(width, 0), pygame.Vector2(10, height), color, show)
|
|
67
|
+
Rect(pygame.Vector2(0, height), pygame.Vector2(width, 10), color, show)
|
|
68
|
+
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
"""
|
|
2
|
+
GameBox - A beginner-friendly Python 2D game development library.
|
|
3
|
+
--------------------------------------------------------------
|
|
4
|
+
GameBox makes it easy to build 2D games with graphics, sound, and UI in just a few lines of code.
|
|
5
|
+
"""
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
__version__ = "0.10.0"
|
|
9
|
+
__author__ = "Sam Fertig"
|
|
10
|
+
|
|
11
|
+
#____imports____
|
|
12
|
+
from .Game import Game
|
|
13
|
+
from .basics.Cammera import Cammera
|
|
14
|
+
from .basics.Shapes import Rect, Circle
|
|
15
|
+
from .helpers.Input import Keys
|
|
16
|
+
from .player.Player import Player
|
|
17
|
+
from .basics.utils import clamp
|
|
18
|
+
from .basics.ui import Image, Text
|
|
19
|
+
from .basics.sound import Sound
|
|
20
|
+
from .tilemap.Tilemap import Tilemap
|
|
21
|
+
|
|
22
|
+
__all__ = [
|
|
23
|
+
"Game",
|
|
24
|
+
"Cammera",
|
|
25
|
+
"Rect",
|
|
26
|
+
"Circle",
|
|
27
|
+
"Keys",
|
|
28
|
+
"Player",
|
|
29
|
+
"clamp",
|
|
30
|
+
"Image",
|
|
31
|
+
"Text",
|
|
32
|
+
"Sound",
|
|
33
|
+
"Tilemap"
|
|
34
|
+
|
|
35
|
+
]
|
|
36
|
+
|
|
37
|
+
|
|
38
|
+
|
|
39
|
+
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import pygame
|
|
2
|
+
from random import randint as Ri
|
|
3
|
+
|
|
4
|
+
from .Net import Global
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
class Cammera:
|
|
8
|
+
def __init__(self, scale: float = 1.0, smooth: float = 1.0):
|
|
9
|
+
|
|
10
|
+
Global.cam = self
|
|
11
|
+
|
|
12
|
+
self.pos = pygame.Vector2(0, 0)
|
|
13
|
+
self.smooth = smooth
|
|
14
|
+
self.zoom = scale
|
|
15
|
+
|
|
16
|
+
self.shakeinfo = [False, 0, 0, False] # [active, duration, power, returnPos]
|
|
17
|
+
|
|
18
|
+
#movement
|
|
19
|
+
self.target = None
|
|
20
|
+
self.offset = None
|
|
21
|
+
|
|
22
|
+
def update(self):
|
|
23
|
+
#addon
|
|
24
|
+
addon = pygame.Vector2(0, 0)
|
|
25
|
+
if self.shakeinfo[0]:
|
|
26
|
+
addon = pygame.Vector2(Ri(-1, 1), Ri(-1, 1)) * self.shakeinfo[2]
|
|
27
|
+
self.shakeinfo[1]-=1
|
|
28
|
+
if self.shakeinfo[1]<=0:
|
|
29
|
+
self.shakeinfo[0] = False
|
|
30
|
+
if self.shakeinfo[3]: self.pos = pygame.Vector2(self.shakeinfo[3])
|
|
31
|
+
|
|
32
|
+
if self.target and hasattr(self.target, "pos"):
|
|
33
|
+
target_pos = self.target.pos
|
|
34
|
+
self.pos = (self.pos + (target_pos + self.offset - self.pos) * self.smooth)
|
|
35
|
+
|
|
36
|
+
self.pos+=addon
|
|
37
|
+
|
|
38
|
+
def set_target(self, target):
|
|
39
|
+
self.target = target
|
|
40
|
+
self.offset = self.pos - target.pos
|
|
41
|
+
|
|
42
|
+
def shake(self, dur, power, returnPos=False):
|
|
43
|
+
self.shakeinfo = [True, dur, power, returnPos]
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import pygame
|
|
2
|
+
import numpy as np
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+
class _global_:
|
|
6
|
+
def __init__(self):
|
|
7
|
+
#screen info
|
|
8
|
+
self.screen: pygame.Surface
|
|
9
|
+
self.screenDim: np.array
|
|
10
|
+
self.bg_color: np.array
|
|
11
|
+
self.winTitle: str
|
|
12
|
+
|
|
13
|
+
self.player = None
|
|
14
|
+
|
|
15
|
+
#time info
|
|
16
|
+
self.clock: pygame.time.Clock
|
|
17
|
+
self.dt: float
|
|
18
|
+
|
|
19
|
+
#game info and data
|
|
20
|
+
#objs in layers 1-5
|
|
21
|
+
self.objs = {"0":[], "1":[], "2":[], "3":[], "4":[], "5":[]}
|
|
22
|
+
self.collision = []
|
|
23
|
+
self.events = None
|
|
24
|
+
self.cam = None
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
Global = _global_()
|
|
28
|
+
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
import pygame
|
|
2
|
+
|
|
3
|
+
from .Net import Global
|
|
4
|
+
|
|
5
|
+
class shape:
|
|
6
|
+
def __init__(self, pos, dim, color, show):
|
|
7
|
+
self.pos = pygame.Vector2(pos)
|
|
8
|
+
self.dim = pygame.Vector2(dim)
|
|
9
|
+
self.color = color
|
|
10
|
+
self.show = show
|
|
11
|
+
|
|
12
|
+
def move_to(self, x, y):
|
|
13
|
+
self.pos = pygame.Vector2(x, y)
|
|
14
|
+
def move_by(self, x, y):
|
|
15
|
+
self.pos += pygame.Vector2(x, y)
|
|
16
|
+
|
|
17
|
+
def scale(self, factor):
|
|
18
|
+
self.dim *= factor
|
|
19
|
+
def set_dim(self, width, height):
|
|
20
|
+
self.dim = pygame.Vector2(width, height)
|
|
21
|
+
def change_dim(self, width, height):
|
|
22
|
+
self.dim += pygame.Vector2(width, height)
|
|
23
|
+
def set_color(self, color):
|
|
24
|
+
self.color = color
|
|
25
|
+
|
|
26
|
+
def collide(self, obj):
|
|
27
|
+
rect = pygame.Rect(self.pos, self.dim)
|
|
28
|
+
if hasattr(obj, 'pos') and hasattr(obj, 'dim'):
|
|
29
|
+
obj_rect = pygame.Rect(obj.pos, obj.dim)
|
|
30
|
+
return rect.colliderect(obj_rect)
|
|
31
|
+
print(f"<GameBox> Error: Object {obj} does not have pos and dim attributes and can't be collided with")
|
|
32
|
+
return False
|
|
33
|
+
|
|
34
|
+
class Rect(shape):
|
|
35
|
+
def __init__(self, pos, dim, color, show=True, collision=True, layer=3):
|
|
36
|
+
super().__init__(pos, dim, color, show)
|
|
37
|
+
self.collision = collision
|
|
38
|
+
self.layer = layer
|
|
39
|
+
|
|
40
|
+
Global.objs[str(layer)].append(self)
|
|
41
|
+
|
|
42
|
+
def update(self):
|
|
43
|
+
if self.show: self.draw()
|
|
44
|
+
|
|
45
|
+
def _addCollision(self):
|
|
46
|
+
if self.collision:
|
|
47
|
+
rect = pygame.Rect(self.pos, self.dim)
|
|
48
|
+
Global.collision.append(rect)
|
|
49
|
+
|
|
50
|
+
def draw(self):
|
|
51
|
+
sp = (self.pos - Global.cam.pos) * Global.cam.zoom
|
|
52
|
+
ss = self.dim * Global.cam.zoom
|
|
53
|
+
pygame.draw.rect(Global.screen, self.color, (sp, ss))
|
|
54
|
+
|
|
55
|
+
def delete(self):
|
|
56
|
+
Global.objs[str(self.layer)].remove(self)
|
|
57
|
+
|
|
58
|
+
class Circle(shape):
|
|
59
|
+
def __init__(self, pos, radius, color, show=True, layer=3):
|
|
60
|
+
super().__init__(pos, pygame.Vector2(radius, radius), color)
|
|
61
|
+
self.collision = False
|
|
62
|
+
self.layer = layer
|
|
63
|
+
Global.objs[str(layer)].append(self)
|
|
64
|
+
|
|
65
|
+
def update(self):
|
|
66
|
+
if self.show: self.draw()
|
|
67
|
+
|
|
68
|
+
def _addCollision(self):
|
|
69
|
+
if self.collision:
|
|
70
|
+
rect = pygame.Rect(self.pos, self.dim)
|
|
71
|
+
Global.collision.append(rect)
|
|
72
|
+
|
|
73
|
+
def draw(self):
|
|
74
|
+
sp = (self.pos - Global.cam.pos) * Global.cam.zoom
|
|
75
|
+
ss = self.dim * Global.cam.zoom
|
|
76
|
+
pygame.draw.circle(Global.screen, self.color, (sp), ss[0]//2)
|
|
77
|
+
|
|
78
|
+
def delete(self):
|
|
79
|
+
Global.objs[str(self.layer)].remove(self)
|
|
80
|
+
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import pygame
|
|
2
|
+
|
|
3
|
+
class Sound:
|
|
4
|
+
def __init__(self, path: str, volume: float = 1.0):
|
|
5
|
+
self.sound = pygame.mixer.Sound(path)
|
|
6
|
+
self.volume = volume
|
|
7
|
+
|
|
8
|
+
def play(self, loops: int = 0, maxtime: int = 0, fade_ms: int = 0):
|
|
9
|
+
self.sound.play(loops, maxtime, fade_ms)
|
|
10
|
+
|
|
11
|
+
def stop(self):
|
|
12
|
+
self.sound.stop()
|
|
13
|
+
|
|
14
|
+
def set_volume(self, volume: float):
|
|
15
|
+
self.volume = volume
|
|
16
|
+
self.sound.set_volume(volume)
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
import pygame
|
|
2
|
+
|
|
3
|
+
from .Net import Global
|
|
4
|
+
|
|
5
|
+
class _image:
|
|
6
|
+
def __init__(self, pos, image, scale, show):
|
|
7
|
+
self.pos = pygame.Vector2(pos)
|
|
8
|
+
self.image = pygame.transform.scale(image, (int(image.get_width() * scale), int(image.get_height() * scale)))
|
|
9
|
+
self.scale = scale
|
|
10
|
+
self.show=show
|
|
11
|
+
|
|
12
|
+
def move_to(self, pos):
|
|
13
|
+
self.pos = pygame.Vector2(pos)
|
|
14
|
+
def move_by(self, x, y):
|
|
15
|
+
self.pos.x += x
|
|
16
|
+
self.pos.y += y
|
|
17
|
+
|
|
18
|
+
def change_scale(self, amount):
|
|
19
|
+
self.scale += amount
|
|
20
|
+
self.image = pygame.transform.scale(self.image, (int(self.image.get_width() * self.scale), int(self.image.get_height() * self.scale)))
|
|
21
|
+
|
|
22
|
+
def load_image(image) -> pygame.Surface:
|
|
23
|
+
if type(image) == str:
|
|
24
|
+
return pygame.image.load(image)
|
|
25
|
+
return image
|
|
26
|
+
|
|
27
|
+
class Image(_image):
|
|
28
|
+
def __init__(self, pos, image, scale, show=True, layer=0):
|
|
29
|
+
super().__init__(pos, load_image(image), scale, show)
|
|
30
|
+
self.layer = layer
|
|
31
|
+
Global.objs[str(self.layer)].append(self)
|
|
32
|
+
|
|
33
|
+
def update(self):
|
|
34
|
+
if self.show: self.draw()
|
|
35
|
+
|
|
36
|
+
def draw(self):
|
|
37
|
+
if Global.cam.zoom != 0:
|
|
38
|
+
image = pygame.transform.scale(self.image, (int(self.image.get_width() * Global.cam.zoom), int(self.image.get_height() * Global.cam.zoom)))
|
|
39
|
+
Global.screen.blit(image, self.pos - Global.cam.pos)
|
|
40
|
+
else:
|
|
41
|
+
Global.screen.blit(self.image, self.pos)
|
|
42
|
+
|
|
43
|
+
class Text:
|
|
44
|
+
def __init__(self, pos, text, font, color, show=True, ui=True, layer=0):
|
|
45
|
+
self.pos = pygame.Vector2(pos)
|
|
46
|
+
self.text = text
|
|
47
|
+
self.font = font
|
|
48
|
+
self.color = color
|
|
49
|
+
self.layer = layer
|
|
50
|
+
self.ui = ui
|
|
51
|
+
Global.objs[str(self.layer)].append(self)
|
|
52
|
+
self.show = show
|
|
53
|
+
|
|
54
|
+
def change(self, text):
|
|
55
|
+
self.text = text
|
|
56
|
+
|
|
57
|
+
def update(self):
|
|
58
|
+
if self.show: self.draw()
|
|
59
|
+
|
|
60
|
+
def draw(self):
|
|
61
|
+
text = self.font.render(self.text, True, self.color)
|
|
62
|
+
#scale if needed
|
|
63
|
+
if Global.cam.zoom != 1.0: text = pygame.transform.scale_by(text, Global.cam.zoom)
|
|
64
|
+
|
|
65
|
+
if self.ui: Global.screen.blit(text, self.pos)
|
|
66
|
+
else:
|
|
67
|
+
sp = self.pos - Global.cam.pos
|
|
68
|
+
Global.screen.blit(text, sp)
|
|
69
|
+
|
|
70
|
+
|
|
@@ -4,6 +4,7 @@ import numpy as np
|
|
|
4
4
|
|
|
5
5
|
def clamp(value, min_value, max_value):
|
|
6
6
|
return max(min(value, max_value), min_value)
|
|
7
|
+
|
|
7
8
|
def moveTward(value, target, speed):
|
|
8
9
|
if value < target:
|
|
9
10
|
value += speed
|
|
@@ -14,4 +15,4 @@ def moveTward(value, target, speed):
|
|
|
14
15
|
def zeroOut(value, max):
|
|
15
16
|
if value < 0 and value > -max: value = 0
|
|
16
17
|
if value > 0 and value < max: value = 0
|
|
17
|
-
return value
|
|
18
|
+
return value
|
gamebox-0.9.2/src/GameBox/helpers/_input.py → gamebox-0.10.0.dev1/src/GameBox/helpers/Input.py
RENAMED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import pygame
|
|
2
2
|
|
|
3
|
-
from ..basics.
|
|
3
|
+
from ..basics.Net import Global
|
|
4
4
|
|
|
5
5
|
|
|
6
6
|
class _keys:
|
|
@@ -61,14 +61,19 @@ class _keys:
|
|
|
61
61
|
|
|
62
62
|
#mouse
|
|
63
63
|
self.mouse_x, self.mouse_y = 0, 0
|
|
64
|
-
def init(self): Global.
|
|
64
|
+
def init(self): Global.objs[str(5)].append(self)
|
|
65
65
|
|
|
66
66
|
def is_pressed(self, key):
|
|
67
|
-
|
|
67
|
+
if Global.events is None: return False
|
|
68
|
+
for event in Global.events:
|
|
68
69
|
if event.type == pygame.KEYDOWN:
|
|
69
70
|
if event.key == key: return True
|
|
70
71
|
return False
|
|
71
72
|
|
|
73
|
+
def is_held(self, key):
|
|
74
|
+
keys = pygame.key.get_pressed()
|
|
75
|
+
return keys[key]
|
|
76
|
+
|
|
72
77
|
def update(self): self.mouse_x, self.mouse_y = pygame.mouse.get_pos()
|
|
73
78
|
|
|
74
79
|
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
import pygame
|
|
2
|
+
|
|
3
|
+
from ..basics.Net import Global
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
def CollisionLogic(vel, pos, dim, sample):
|
|
7
|
+
x, y = pos
|
|
8
|
+
vx, vy = vel
|
|
9
|
+
|
|
10
|
+
x, y, vx, vy = _Collisions(x, y, vx, vy, dim, Global.collision)
|
|
11
|
+
#x, y, vx, vy = _tilemapCollisions(x, y, vx, vy, dim, sample)
|
|
12
|
+
|
|
13
|
+
pos = pygame.Vector2(x, y)
|
|
14
|
+
vel = pygame.Vector2(vx, vy)
|
|
15
|
+
|
|
16
|
+
return pos, vel
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
def _Collisions(x, y, vx, vy, dim, shapes):
|
|
20
|
+
# Apply movement
|
|
21
|
+
x += vx
|
|
22
|
+
y += vy
|
|
23
|
+
|
|
24
|
+
rect = pygame.Rect(x, y, dim.x, dim.y)
|
|
25
|
+
|
|
26
|
+
for collision in shapes:
|
|
27
|
+
if not rect.colliderect(collision):
|
|
28
|
+
continue
|
|
29
|
+
|
|
30
|
+
# Calculate overlap on each side
|
|
31
|
+
overlap_left = rect.right - collision.left
|
|
32
|
+
overlap_right = collision.right - rect.left
|
|
33
|
+
overlap_top = rect.bottom - collision.top
|
|
34
|
+
overlap_bottom = collision.bottom - rect.top
|
|
35
|
+
|
|
36
|
+
# Find smallest overlap
|
|
37
|
+
min_x = min(overlap_left, overlap_right)
|
|
38
|
+
min_y = min(overlap_top, overlap_bottom)
|
|
39
|
+
|
|
40
|
+
# Resolve on the axis with least penetration
|
|
41
|
+
if min_x < min_y:
|
|
42
|
+
if overlap_left < overlap_right:
|
|
43
|
+
rect.right = collision.left
|
|
44
|
+
else:
|
|
45
|
+
rect.left = collision.right
|
|
46
|
+
vx = 0
|
|
47
|
+
else:
|
|
48
|
+
if overlap_top < overlap_bottom:
|
|
49
|
+
rect.bottom = collision.top
|
|
50
|
+
else:
|
|
51
|
+
rect.top = collision.bottom
|
|
52
|
+
vy = 0
|
|
53
|
+
|
|
54
|
+
return rect.x, rect.y, vx, vy
|
|
55
|
+
|
|
56
|
+
|
|
57
|
+
def _tilemapCollisions(x, y, vx, vy, dim, sampleSize):
|
|
58
|
+
for map in Global.tilemaps:
|
|
59
|
+
#get player tilemap pos
|
|
60
|
+
tx = x//map.tileDim[0]
|
|
61
|
+
ty = y//map.tileDim[1]
|
|
62
|
+
#get tiles around player
|
|
63
|
+
collisions = []
|
|
64
|
+
for yIndex in range(-sampleSize, sampleSize):
|
|
65
|
+
for xIndex in range(-sampleSize, sampleSize):
|
|
66
|
+
#if point not on map, skip
|
|
67
|
+
if tx+xIndex < 0 or tx+xIndex >= map.mapDim[0] or ty+yIndex < 0 or ty+yIndex >= map.mapDim[1]: continue
|
|
68
|
+
#get shape
|
|
69
|
+
tile = str(map.map[int(ty+yIndex)][int(tx+xIndex)])
|
|
70
|
+
if tile not in map.collisionDict: continue
|
|
71
|
+
shape = map.collisionDict[str(tile)]
|
|
72
|
+
rect = getattr(map.collisionShapes, shape).copy()
|
|
73
|
+
rect.x += (tx+xIndex)*map.tileDim[0]
|
|
74
|
+
rect.y += (ty+yIndex)*map.tileDim[1]
|
|
75
|
+
collisions.append(rect)
|
|
76
|
+
#collision math
|
|
77
|
+
x, y, vx, vy = _Collisions(x, y, vx, vy, dim, collisions)
|
|
78
|
+
return x, y, vx, vy
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
import pygame
|
|
2
|
+
|
|
3
|
+
from ..basics.Net import Global
|
|
4
|
+
from ._playerPhysics import playerPhysics
|
|
5
|
+
from ._playerControler import playerController
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
class Player:
|
|
9
|
+
def __init__(self, pos, dim, color, show=True, layer=3):
|
|
10
|
+
self.pos = pygame.Vector2(pos)
|
|
11
|
+
self.dim = pygame.Vector2(dim)
|
|
12
|
+
self.vel = pygame.Vector2(0, 0)
|
|
13
|
+
self.color = color
|
|
14
|
+
|
|
15
|
+
self.physics = None
|
|
16
|
+
self.move = playerController(self)
|
|
17
|
+
self.show = show
|
|
18
|
+
|
|
19
|
+
self.sampleSize = 5
|
|
20
|
+
self.layer = layer
|
|
21
|
+
|
|
22
|
+
Global.objs[str(layer)].append(self)
|
|
23
|
+
#Global.player = self
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
def copy(self):
|
|
27
|
+
p = Player(self.pos, self.dim, self.color, self.show, self.layer)
|
|
28
|
+
p.add_physics(self.physics.speed, self.physics.gravity, self.physics.jumpForce, self.physics.maxV, self.physics.friction)
|
|
29
|
+
return p
|
|
30
|
+
|
|
31
|
+
def add_physics(self, speed: float = 7.0, gravity: float = 5.5, jumpForce: float = 10.0, maxV: tuple = (25, 25), friction: tuple = (0.8, 0.8)):
|
|
32
|
+
self.physics = playerPhysics(self, speed, gravity, jumpForce, pygame.Vector2(maxV), pygame.Vector2(friction))
|
|
33
|
+
|
|
34
|
+
def update(self):
|
|
35
|
+
if self.physics: self.physics.update()
|
|
36
|
+
if self.show: self.draw()
|
|
37
|
+
|
|
38
|
+
#--debug func--
|
|
39
|
+
def draw(self):
|
|
40
|
+
sp = (self.pos - Global.cam.pos) * Global.cam.zoom
|
|
41
|
+
ss = self.dim * Global.cam.zoom
|
|
42
|
+
pygame.draw.rect(Global.screen, self.color, [sp, ss])
|
|
43
|
+
|
|
44
|
+
def set_sample_size(self, size):
|
|
45
|
+
self.sampleSize = size
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import pygame
|
|
2
|
+
|
|
3
|
+
from ..helpers.Input import Keys
|
|
4
|
+
|
|
5
|
+
class playerController:
|
|
6
|
+
def __init__(self, player):
|
|
7
|
+
self.p = player
|
|
8
|
+
|
|
9
|
+
def by_WSAD(self, speed):
|
|
10
|
+
if Keys.is_held(Keys.w): self.p.vel.y -= speed
|
|
11
|
+
if Keys.is_held(Keys.s): self.p.vel.y += speed
|
|
12
|
+
if Keys.is_held(Keys.a): self.p.vel.x -= speed
|
|
13
|
+
if Keys.is_held(Keys.d): self.p.vel.x += speed
|
|
14
|
+
|
|
15
|
+
def by_arrows(self, speed):
|
|
16
|
+
if Keys.is_held(Keys.up): self.p.vel.y -= speed
|
|
17
|
+
if Keys.is_held(Keys.down): self.p.vel.y += speed
|
|
18
|
+
if Keys.is_held(Keys.left): self.p.vel.x -= speed
|
|
19
|
+
if Keys.is_held(Keys.right): self.p.vel.x += speed
|
|
20
|
+
|
|
21
|
+
def platformor_by_WSAD(self, speed):
|
|
22
|
+
if Keys.is_pressed(Keys.w): self.p.vel.y -= speed
|
|
23
|
+
if Keys.is_held(Keys.a): self.p.vel.x -= speed
|
|
24
|
+
if Keys.is_held(Keys.d): self.p.vel.x += speed
|
|
25
|
+
|
|
26
|
+
def platformor_by_arrows(self, speed):
|
|
27
|
+
if Keys.is_pressed(Keys.up): self.p.vel.y -= speed
|
|
28
|
+
if Keys.is_held(Keys.left): self.p.vel.x -= speed
|
|
29
|
+
if Keys.is_held(Keys.right): self.p.vel.x += speed
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import pygame
|
|
2
|
+
|
|
3
|
+
from ..basics.Net import Global
|
|
4
|
+
from ..basics.utils import clamp, zeroOut
|
|
5
|
+
|
|
6
|
+
from ..helpers._collisions import CollisionLogic
|
|
7
|
+
|
|
8
|
+
class playerPhysics:
|
|
9
|
+
def __init__(self, player, speed, gravity, jumpForce, maxV, friction):
|
|
10
|
+
self.player = player
|
|
11
|
+
self.speed = speed
|
|
12
|
+
self.gravity = gravity
|
|
13
|
+
self.jumpForce = jumpForce
|
|
14
|
+
self.maxV = maxV
|
|
15
|
+
self.friction = friction
|
|
16
|
+
|
|
17
|
+
def update(self):
|
|
18
|
+
#clamp velocities
|
|
19
|
+
self.player.vel.x = clamp(self.player.vel.x, -self.maxV.x, self.maxV.x)
|
|
20
|
+
self.player.vel.y = clamp(self.player.vel.y, -self.maxV.y, self.maxV.y)
|
|
21
|
+
|
|
22
|
+
#apply gravity
|
|
23
|
+
self.player.vel.y += self.gravity
|
|
24
|
+
|
|
25
|
+
#apply friction
|
|
26
|
+
self.player.vel.x *= self.friction.x
|
|
27
|
+
self.player.vel.y *= self.friction.y
|
|
28
|
+
|
|
29
|
+
#zero out very small velocities to prevent drift
|
|
30
|
+
self.player.vel.x = zeroOut(self.player.vel.x, 0.01)
|
|
31
|
+
self.player.vel.y = zeroOut(self.player.vel.y, 0.01)
|
|
32
|
+
|
|
33
|
+
#update position
|
|
34
|
+
self.player.pos, self.player.vel = CollisionLogic(self.player.vel, self.player.pos, self.player.dim, self.player.sampleSize)
|
|
35
|
+
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
import pygame
|
|
2
|
+
import numpy as np
|
|
3
|
+
|
|
4
|
+
from ..basics.Net import Global
|
|
5
|
+
from ..basics.ui import load_image
|
|
6
|
+
|
|
7
|
+
class Tilemap:
|
|
8
|
+
def __init__(self, tilesetImage, tileDim, scale, layer=4, show=True):
|
|
9
|
+
self.tilemap = load_image(tilesetImage)
|
|
10
|
+
|
|
11
|
+
self.tileDim = pygame.Vector2(tileDim)
|
|
12
|
+
self.scaleDim = pygame.Vector2(tileDim) * scale
|
|
13
|
+
self.scale = scale
|
|
14
|
+
self.mapDim = mapDim
|
|
15
|
+
|
|
16
|
+
self.fill = fill
|
|
17
|
+
self.layer = layer
|
|
18
|
+
self.show = show
|
|
19
|
+
Global.objs[str(self.layer)].append(self)
|
|
20
|
+
|
|
21
|
+
#load images and create basic tilemap
|
|
22
|
+
self.map = {}
|
|
23
|
+
self.tiles: Dict[int, pygame.Surface] = {}
|
|
24
|
+
self.images: Dict[int, pygame.Surface] = {}
|
|
25
|
+
tile = 1
|
|
26
|
+
#split image into tiles
|
|
27
|
+
for y in range(mapDim[1]):
|
|
28
|
+
for x in range(mapDim[0]):
|
|
29
|
+
try:
|
|
30
|
+
self.images[tile] = self.tilemap.subsurface(pygame.Rect(x * self.tileDim.x, y * self.tileDim.y, self.tileDim.x, self.tileDim.y))
|
|
31
|
+
self.tiles[tile] = pygame.transform.scale_by(self.images[tile], self.scale)
|
|
32
|
+
except:
|
|
33
|
+
pass
|
|
34
|
+
tile += 1
|
|
35
|
+
|
|
36
|
+
def update(self):
|
|
37
|
+
if self.show: self.draw()
|
|
38
|
+
|
|
39
|
+
def draw(self):
|
|
40
|
+
for key in self.map:
|
|
41
|
+
tile = self.map[key]
|
|
42
|
+
image = self.tiles[tile['type']]
|
|
43
|
+
pos = tile['pos']
|
|
44
|
+
|
|
45
|
+
|
|
46
|
+
|