Add Objects

This commit is contained in:
Michał Gdula 2023-01-28 13:40:12 +00:00
parent ccb5394b00
commit b9f02c8268
18 changed files with 172 additions and 33 deletions

23
main.py
View file

@ -5,6 +5,8 @@ from map import *
from player import *
from raycasting import *
from object_renderer import *
#from sprite_object import *
from object_handler import *
class Game:
def __init__(self):
@ -20,19 +22,30 @@ class Game:
self.player = Player(self)
self.object_renderer = ObjectRenderer(self)
self.raycasting = RayCasting(self)
#self.static_sprites = SpriteObject(self)
#self.animated_sprites = AnimatedSprite(self)
self.object_handler = ObjectHandler(self)
def update(self):
self.player.update()
self.raycasting.update()
#self.static_sprites.update()
#self.animated_sprites.update()
self.object_handler.update()
pg.display.flip()
self.delta_time = self.clock.tick(FPS)
pg.display.set_caption(f"FPS: {self.clock.get_fps() : 0.2f}")
if DEBUG_MODE:
pg.display.set_caption(f"Garbage Game - FPS: {self.clock.get_fps() : 0.2f} - Delta Time: {self.delta_time / 1000 : 0.2f}")
else:
pg.display.set_caption(f"Garbage Game")
def draw(self):
#self.screen.fill('black')
self.object_renderer.draw()
#self.map.draw()
#self.player.draw()
if DEBUG_MODE:
self.screen.fill('black')
self.map.draw()
self.player.draw()
else:
self.object_renderer.draw()
def check_events(self):
for event in pg.event.get():

8
map.py
View file

@ -10,10 +10,10 @@ mini_map = [
[1, _, _, 3, 3, 3, 3, _, _, _, _, _, _, _, _, 1],
[1, _, _, _, _, _, _, _, _, _, _, _, _, _, _, 1],
[1, _, _, _, 4, _, _, _, 4, _, _, _, _, _, _, 1],
[1, 1, 1, 3, 1, 3, 1, 1, 1, 3, _, _, 3, 1, 1, 1],
[1, 1, 1, 1, 1, 1, 1, 1, 1, 3, _, _, 3, 1, 1, 1],
[1, 1, 1, 1, 1, 1, 1, 1, 1, 3, _, _, 3, 1, 1, 1],
[1, 1, 3, 1, 1, 1, 1, 1, 1, 3, _, _, 3, 1, 1, 1],
[1, 1, 1, 3, 1, 3, _, 1, 1, 3, _, _, 3, 1, 1, 1],
[1, 1, 1, 1, _, _, _, 1, 1, 3, _, _, 3, 1, 1, 1],
[1, 1, 1, _, _, 1, 1, 1, 1, 3, _, _, 3, 1, 1, 1],
[1, 1, 3, _, 1, 1, 1, 1, 1, 3, _, _, 3, 1, 1, 1],
[1, 4, _, _, _, _, _, _, _, _, _, _, _, _, _, 1],
[3, _, _, _, _, _, _, _, _, _, _, _, _, _, _, 1],
[1, _, _, _, _, _, _, _, _, _, _, _, _, _, _, 1],

28
object_handler.py Normal file
View file

@ -0,0 +1,28 @@
from sprite_object import *
class ObjectHandler:
def __init__(self, game):
self.game = game
self.sprite_list = []
self.static_sprite_path = 'resources/sprites/static_sprites/'
self.animated_sprite_path = 'resources/sprites/animated_sprites/'
add_sprite = self.add_sprite
# Sprite Map
add_sprite(SpriteObject(game))
add_sprite(AnimatedSprite(game))
add_sprite(AnimatedSprite(game, path=self.animated_sprite_path + 'red_light/0.png', pos=(14.5, 5.5)))
add_sprite(AnimatedSprite(game, path=self.animated_sprite_path + 'red_light/0.png', pos=(14.5, 7.5)))
add_sprite(AnimatedSprite(game, path=self.animated_sprite_path + 'red_light/0.png', pos=(12.5, 7.5)))
add_sprite(AnimatedSprite(game, path=self.animated_sprite_path + 'red_light/0.png', pos=(9.5, 7.5)))
add_sprite(AnimatedSprite(game, path=self.animated_sprite_path + 'red_light/0.png', pos=(14.5, 12.5)))
add_sprite(AnimatedSprite(game, path=self.animated_sprite_path + 'red_light/0.png', pos=(9.5, 20.5)))
add_sprite(AnimatedSprite(game, path=self.animated_sprite_path + 'red_light/0.png', pos=(10.5, 20.5)))
add_sprite(AnimatedSprite(game, path=self.animated_sprite_path + 'red_light/0.png', pos=(3.5, 14.5)))
add_sprite(AnimatedSprite(game, path=self.animated_sprite_path + 'red_light/0.png', pos=(3.5, 18.5)))
def update(self):
[sprite.update() for sprite in self.sprite_list]
def add_sprite(self, sprite):
self.sprite_list.append(sprite)

View file

@ -22,7 +22,7 @@ class ObjectRenderer:
pg.draw.rect(self.screen, FLOOR_COLOR, (0, HALF_HEIGHT, WIDTH, HALF_HEIGHT))
def render_game_objects(self):
list_objects = self.game.raycasting.objects_to_render
list_objects = sorted(self.game.raycasting.objects_to_render, key=lambda t: t[0], reverse=True)
for depth, image, pos in list_objects:
colour = [255 / (1 + depth ** 3.2 * 0.0002)] * 3
image.fill(colour, special_flags=pg.BLEND_MULT)
@ -39,6 +39,6 @@ class ObjectRenderer:
1: self.get_texture('resources/textures/1.png'),
2: self.get_texture('resources/textures/2.png'),
3: self.get_texture('resources/textures/3.png'),
4: self.get_texture('resources/textures/4.jpg'),
5: self.get_texture('resources/textures/1.jpg'),
4: self.get_texture('resources/textures/4.png'),
5: self.get_texture('resources/textures/1.png'),
}

View file

@ -6,12 +6,12 @@ class Player:
def __init__(self, game):
self.game = game
self.x, self.y = PLAYER_POS
self.rot = PLAYER_ROT
self.angle = PLAYER_ROT
def movement(self):
# Initialize variables
sin_a = math.sin(self.rot)
cos_a = math.cos(self.rot)
sin_a = math.sin(self.angle)
cos_a = math.cos(self.angle)
dx, dy = 0, 0
player_speed = PLAYER_SPEED * self.game.delta_time
player_speed_sin = player_speed * sin_a
@ -35,12 +35,12 @@ class Player:
# set player position
self.check_collision(dx, dy)
# player rotation
if keys[pg.K_LEFT]:
self.rot -= PLAYER_ROT_SPEED * self.game.delta_time
if keys[pg.K_RIGHT]:
self.rot += PLAYER_ROT_SPEED * self.game.delta_time
self.rot %= 2 * math.tau # tau = 2 * pi
# player rotation with arrow keys
#if keys[pg.K_LEFT]:
# self.angle -= PLAYER_ROT_SPEED * self.game.delta_time
#if keys[pg.K_RIGHT]:
# self.angle += PLAYER_ROT_SPEED * self.game.delta_time
self.angle %= math.tau # tau = 2 * pi
def check_wall(self, x, y):
return (x, y) not in self.game.map.world_map
@ -54,8 +54,8 @@ class Player:
def draw(self):
pg.draw.line(self.game.screen, 'green', (self.x * 100, self.y * 100),
(self.x * 100 + WIDTH * math.cos(self.rot),
self.y * 100 + WIDTH * math.sin(self.rot)), 2)
(self.x * 100 + WIDTH * math.cos(self.angle),
self.y * 100 + WIDTH * math.sin(self.angle)), 2)
pg.draw.circle(self.game.screen, 'red', (self.x * 100, self.y * 100), 15)
def mouse_control(self):
@ -64,7 +64,7 @@ class Player:
pg.mouse.set_pos([HALF_WIDTH, HALF_HEIGHT])
self.rel = pg.mouse.get_rel()[0]
self.rel = max(-MOUSE_MAX_SPEED, min(MOUSE_MAX_SPEED, self.rel))
self.rot += self.rel * MOUSE_SENSITIVITY * self.game.delta_time
self.angle += self.rel * MOUSE_SENSITIVITY * self.game.delta_time
def update(self):
self.movement()

View file

@ -38,7 +38,7 @@ class RayCasting():
texture_vert, texture_horz = 1, 1
ray_angle = self.game.player.rot - HALF_FOV + 0.0001 # 0.0001 to avoid division by zero
ray_angle = self.game.player.angle - HALF_FOV + 0.0001 # 0.0001 to avoid division by zero
for ray in range(NUM_RAYS):
sin_a = math.sin(ray_angle)
cos_a = math.cos(ray_angle)
@ -90,11 +90,13 @@ class RayCasting():
offset = (1 - x_horz) if sin_a > 0 else x_horz
# Draw the ray for debugging
#pg.draw.line(self.game.screen, 'blue', (ox * 100, oy * 100),
# (100 * ox + 100 * depth * cos_a, 100 * oy + 100 * depth * sin_a), 1)
if DEBUG_MODE:
pg.draw.line(self.game.screen, 'blue', (ox * 100, oy * 100),
(100 * ox + 100 * depth * cos_a, 100 * oy + 100 * depth * sin_a), 1)
# Remove fish-eye effect
depth *= math.cos(self.game.player.rot - ray_angle)
if FISH_EYE_FIX:
depth *= math.cos(self.game.player.angle - ray_angle)
# Projection
proj_height = SCREEN_DIST / (depth + 0.0001) # 0.0001 to avoid division by zero

Binary file not shown.

After

Width:  |  Height:  |  Size: 64 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 62 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 64 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 66 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 63 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 61 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 63 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 64 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 243 KiB

BIN
resources/textures/2.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 276 KiB

View file

@ -4,12 +4,12 @@ import math
RES = WIDTH, HEIGHT = 1600, 900
HALF_WIDTH = WIDTH // 2
HALF_HEIGHT = HEIGHT // 2
FPS = 0 # 0 = unlimited
FPS = 0 # 0 = unlimited
PLAYER_POS = 1.5, 5 # player position on the map
PLAYER_POS = 1.5, 5 # player position on the map
PLAYER_ROT = 0
PLAYER_SPEED = 0.004
PLAYER_ROT_SPEED = 0.004
PLAYER_SPEED = 0.002 # player speed
PLAYER_ROT_SPEED = 0.004 # player rotation speed
PLAYER_SIZE_SCALE = 60
MOUSE_SENSITIVITY = 0.0003
@ -31,3 +31,8 @@ SCALE = WIDTH // NUM_RAYS
TEXTURE_SIZE = 256
HALF_TEXTURE_SIZE = TEXTURE_SIZE // 2
# DEBUG SETTINGS
DEBUG_MODE = False # show debug info
FISH_EYE_FIX = True # fix fish eye effect

91
sprite_object.py Normal file
View file

@ -0,0 +1,91 @@
import pygame as pg
from settings import *
import os
from collections import deque
class SpriteObject:
def __init__(self, game, path='resources/sprites/static_sprites/candlebra.png',
pos=(10.5, 3.5), scale=0.7, shift=0.27):
self.game = game
self.player = game.player
self.x, self.y = pos
self.image = pg.image.load(path).convert_alpha()
self.IMAGE_WIDTH = self.image.get_width()
self.IMAGE_HALF_WIDTH = self.image.get_width() // 2
self.IMAGE_RATIO = self.IMAGE_WIDTH / self.image.get_height()
self.dx, self.dy, self.theta, self.screen_x, self.dist, self.norm_dist = 0, 0, 0, 0, 1, 1
self.sprite_half_width = 0
self.SPRITE_SCALE = scale
self.SPRITE_HEIGHT_SHIFT = shift
def get_sprite_projection(self):
proj = SCREEN_DIST / self.norm_dist * self.SPRITE_SCALE
proj_width, proj_height = proj * self.IMAGE_RATIO, proj
image = pg.transform.scale(self.image, (proj_width, proj_height))
self.sprite_half_width = proj_width // 2
height_shift = proj_height * self.SPRITE_HEIGHT_SHIFT
pos = self.screen_x - self.sprite_half_width, HALF_HEIGHT - \
proj_height // 2 + height_shift
self.game.raycasting.objects_to_render.append(
(self.norm_dist, image, pos))
def get_sprite(self):
dx = self.x - self.player.x
dy = self.y - self.player.y
self.dx, self.dy = dx, dy
self.theta = math.atan2(dy, dx)
delta = self.theta - self.player.angle
if (dx > 0 and self.player.angle > math.pi) or (dx < 0 and dy < 0):
delta += math.tau
delta_rays = delta / DELTA_ANGLE
self.screen_x = (HALF_NUM_RAYS + delta_rays) * SCALE
self.dist = math.hypot(dx, dy)
self.norm_dist = self.dist * math.cos(delta)
if -self.IMAGE_HALF_WIDTH < self.screen_x < (WIDTH + self.IMAGE_HALF_WIDTH) and self.norm_dist > 0.5:
self.get_sprite_projection()
def update(self):
self.get_sprite()
class AnimatedSprite(SpriteObject):
def __init__(self, game, path='resources/sprites/animated_sprites/green_light/0.png',
pos=(11.5, 3.5), scale=0.8, shift=0.15, animation_time=120):
super().__init__(game, path, pos, scale, shift)
self.animation_time = animation_time
self.path = path.rsplit('/', 1)[0]
self.images = self.get_images(self.path)
self.animation_time_prev = pg.time.get_ticks()
self.animation_trigger = False
def update(self):
super().update()
self.check_animation_time()
self.animate(self.images)
def animate(self, images):
if self.animation_trigger:
images.rotate(-1)
self.image = images[0]
def check_animation_time(self):
self.animation_trigger = False
time_now = pg.time.get_ticks()
if time_now - self.animation_time_prev > self.animation_time:
self.animation_time_prev = time_now
self.animation_trigger = True
def get_images(self, path):
images = deque()
for file_name in os.listdir(path):
if os.path.isfile(os.path.join(path, file_name)):
img = pg.image.load(path + '/' + file_name).convert_alpha()
images.append(img)
return images