Doompart1
						commit
						81a9243277
					
				|  | @ -0,0 +1,156 @@ | |||
| import pygame | ||||
| from settings import * | ||||
| from ray_casting import ray_casting | ||||
| from map import mini_map | ||||
| from collections import deque | ||||
| from random import  randrange | ||||
| import sys | ||||
| 
 | ||||
| class Drawing: | ||||
|     def __init__(self, sc, sc_map, player, clock): | ||||
|         self.sc = sc | ||||
|         self.sc_map = sc_map | ||||
|         self.player = player | ||||
|         self.clock = clock | ||||
|         self.font = pygame.font.SysFont('Arial', 36, bold=True) | ||||
|         self.font_win = pygame.font.Font('font/font.ttf', 144) | ||||
|         self.textures = {1: pygame.image.load('img/wall3.png').convert(), | ||||
|                          2: pygame.image.load('img/wall4.png').convert(), | ||||
|                          3: pygame.image.load('img/wall5.png').convert(), | ||||
|                          4: pygame.image.load('img/wall6.png').convert(), | ||||
|                          'S': pygame.image.load('img/sky2.png').convert() | ||||
|                          } | ||||
|         # menu | ||||
|         self.menu_trigger = True | ||||
|         self.menu_picture = pygame.image.load('img/bg.jpg').convert() | ||||
|         # weapon parameters | ||||
|         self.weapon_base_sprite = pygame.image.load('sprites/weapons/shotgun/base/0.png').convert_alpha() | ||||
|         self.weapon_shot_animation = deque([pygame.image.load(f'sprites/weapons/shotgun/shot/{i}.png').convert_alpha() | ||||
|                                             for i in range(20)]) | ||||
|         self.weapon_rect = self.weapon_base_sprite.get_rect() | ||||
|         self.weapon_pos = (HALF_WIDTH - self.weapon_rect.width // 2, HEIGHT - self.weapon_rect.height) | ||||
|         self.shot_length = len(self.weapon_shot_animation) | ||||
|         self.shot_length_count = 0 | ||||
|         self.shot_animation_speed = 3 | ||||
|         self.shot_animation_count = 0 | ||||
|         self.shot_animation_trigger = True | ||||
|         self.shot_sound = pygame.mixer.Sound('sound/shotgun.wav') | ||||
|         # sfx parameters | ||||
|         self.sfx = deque([pygame.image.load(f'sprites/weapons/sfx/{i}.png').convert_alpha() for i in range(9)]) | ||||
|         self.sfx_length_count = 0 | ||||
|         self.sfx_length = len(self.sfx) | ||||
| 
 | ||||
|     def background(self, angle): | ||||
|         sky_offset = -10 * math.degrees(angle) % WIDTH | ||||
|         self.sc.blit(self.textures['S'], (sky_offset, 0)) | ||||
|         self.sc.blit(self.textures['S'], (sky_offset - WIDTH, 0)) | ||||
|         self.sc.blit(self.textures['S'], (sky_offset + WIDTH, 0)) | ||||
|         pygame.draw.rect(self.sc, DARKGRAY, (0, HALF_HEIGHT, WIDTH, HALF_HEIGHT)) | ||||
| 
 | ||||
|     def world(self, world_objects): | ||||
|         for obj in sorted(world_objects, key=lambda n: n[0], reverse=True): | ||||
|             if obj[0]: | ||||
|                 _, object, object_pos = obj | ||||
|                 self.sc.blit(object, object_pos) | ||||
| 
 | ||||
|     def fps(self, clock): | ||||
|         display_fps = str(int(clock.get_fps())) | ||||
|         render = self.font.render(display_fps, 0, DARKORANGE) | ||||
|         self.sc.blit(render, FPS_POS) | ||||
| 
 | ||||
|     def mini_map(self, player): | ||||
|         self.sc_map.fill(BLACK) | ||||
|         map_x, map_y = player.x // MAP_SCALE, player.y // MAP_SCALE | ||||
|         pygame.draw.line(self.sc_map, YELLOW, (map_x, map_y), (map_x + 12 * math.cos(player.angle), | ||||
|                                                  map_y + 12 * math.sin(player.angle)), 2) | ||||
|         pygame.draw.circle(self.sc_map, RED, (int(map_x), int(map_y)), 5) | ||||
|         for x, y in mini_map: | ||||
|             pygame.draw.rect(self.sc_map, DARKBROWN, (x, y, MAP_TILE, MAP_TILE)) | ||||
|         self.sc.blit(self.sc_map, MAP_POS) | ||||
| 
 | ||||
|     def player_weapon(self, shots): | ||||
|         if self.player.shot: | ||||
|             if not self.shot_length_count: | ||||
|                 self.shot_sound.play() | ||||
|             self.shot_projection = min(shots)[1] // 2 | ||||
|             self.bullet_sfx() | ||||
|             shot_sprite = self.weapon_shot_animation[0] | ||||
|             self.sc.blit(shot_sprite, self.weapon_pos) | ||||
|             self.shot_animation_count += 1 | ||||
|             if self.shot_animation_count == self.shot_animation_speed: | ||||
|                 self.weapon_shot_animation.rotate(-1) | ||||
|                 self.shot_animation_count = 0 | ||||
|                 self.shot_length_count += 1 | ||||
|                 self.shot_animation_trigger = False | ||||
|             if self.shot_length_count == self.shot_length: | ||||
|                 self.player.shot = False | ||||
|                 self.shot_length_count = 0 | ||||
|                 self.sfx_length_count = 0 | ||||
|                 self.shot_animation_trigger = True | ||||
|         else: | ||||
|             self.sc.blit(self.weapon_base_sprite, self.weapon_pos) | ||||
| 
 | ||||
|     def bullet_sfx(self): | ||||
|         if self.sfx_length_count < self.sfx_length: | ||||
|             sfx = pygame.transform.scale(self.sfx[0], (self.shot_projection, self.shot_projection)) | ||||
|             sfx_rect = sfx.get_rect() | ||||
|             self.sc.blit(sfx, (HALF_WIDTH - sfx_rect.w // 2, HALF_HEIGHT - sfx_rect.h // 2)) | ||||
|             self.sfx_length_count += 1 | ||||
|             self.sfx.rotate(-1) | ||||
| 
 | ||||
| 
 | ||||
|     def win(self): | ||||
|         render = self.font_win.render('YOU WIN!!!', 1, (randrange(40, 120), 0, 0)) | ||||
|         rect = pygame.Rect(0, 0, 1000, 300) | ||||
|         rect.center = HALF_WIDTH, HALF_HEIGHT | ||||
|         pygame.draw.rect(self.sc, BLACK, rect, border_radius=50) | ||||
|         self.sc.blit(render, (rect.centerx - 430, rect.centery - 140)) | ||||
|         pygame.display.flip() | ||||
|         self.clock.tick(15) | ||||
| 
 | ||||
|     def menu(self): | ||||
|         x = 0 | ||||
|         button_font = pygame.font.Font('font/font.ttf', 72) | ||||
|         label_font = pygame.font.Font('font/font1.otf', 400) | ||||
|         start = button_font.render('START', 1, pygame.Color('lightgray')) | ||||
|         button_start = pygame.Rect(0, 0, 400, 150) | ||||
|         button_start.center = HALF_WIDTH, HALF_HEIGHT | ||||
|         exit = button_font.render('EXIT', 1, pygame.Color('lightgray')) | ||||
|         button_exit = pygame.Rect(0, 0, 400, 150) | ||||
|         button_exit.center = HALF_WIDTH, HALF_HEIGHT + 200 | ||||
| 
 | ||||
|         while self.menu_trigger: | ||||
|             for event in pygame.event.get(): | ||||
|                 if event.type == pygame.QUIT: | ||||
|                     pygame.quit() | ||||
|                     sys.exit() | ||||
| 
 | ||||
|             self.sc.blit(self.menu_picture, (0, 0), (x % WIDTH, HALF_HEIGHT, WIDTH, HEIGHT)) | ||||
|             x += 1 | ||||
| 
 | ||||
|             pygame.draw.rect(self.sc, BLACK, button_start, border_radius=25, width=10) | ||||
|             self.sc.blit(start, (button_start.centerx - 130, button_start.centery - 70)) | ||||
| 
 | ||||
|             pygame.draw.rect(self.sc, BLACK, button_exit, border_radius=25, width=10) | ||||
|             self.sc.blit(exit, (button_exit.centerx - 85, button_exit.centery - 70)) | ||||
| 
 | ||||
|             color = randrange(40) | ||||
|             label = label_font.render('DOOMPy', 1, (color, color, color)) | ||||
|             self.sc.blit(label, (15, -30)) | ||||
| 
 | ||||
|             mouse_pos = pygame.mouse.get_pos() | ||||
|             mouse_click = pygame.mouse.get_pressed() | ||||
|             if button_start.collidepoint(mouse_pos): | ||||
|                 pygame.draw.rect(self.sc, BLACK, button_start, border_radius=25) | ||||
|                 self.sc.blit(start, (button_start.centerx - 130, button_start.centery - 70)) | ||||
|                 if mouse_click[0]: | ||||
|                     self.menu_trigger = False | ||||
|             elif button_exit.collidepoint(mouse_pos): | ||||
|                 pygame.draw.rect(self.sc, BLACK, button_exit, border_radius=25) | ||||
|                 self.sc.blit(exit, (button_exit.centerx - 85, button_exit.centery - 70)) | ||||
|                 if mouse_click[0]: | ||||
|                     pygame.quit() | ||||
|                     sys.exit() | ||||
| 
 | ||||
|             pygame.display.flip() | ||||
|             self.clock.tick(20) | ||||
|  | @ -0,0 +1,105 @@ | |||
| from settings import * | ||||
| from map import world_map | ||||
| from ray_casting import mapping | ||||
| import math | ||||
| import pygame | ||||
| from numba import njit | ||||
| 
 | ||||
| @njit(fastmath=True, cache=True) | ||||
| def ray_casting_npc_player(npc_x, npc_y, blocked_doors, world_map, player_pos): | ||||
|     ox, oy = player_pos | ||||
|     xm, ym = mapping(ox, oy) | ||||
|     delta_x, delta_y = ox - npc_x, oy - npc_y | ||||
|     cur_angle = math.atan2(delta_y, delta_x) | ||||
|     cur_angle += math.pi | ||||
| 
 | ||||
|     sin_a = math.sin(cur_angle) | ||||
|     sin_a = sin_a if sin_a else 0.000001 | ||||
|     cos_a = math.cos(cur_angle) | ||||
|     cos_a = cos_a if cos_a else 0.000001 | ||||
| 
 | ||||
|     # verticals | ||||
|     x, dx = (xm + TILE, 1) if cos_a >= 0 else (xm, -1) | ||||
|     for i in range(0, int(abs(delta_x)) // TILE): | ||||
|         depth_v = (x - ox) / cos_a | ||||
|         yv = oy + depth_v * sin_a | ||||
|         tile_v = mapping(x + dx, yv) | ||||
|         if tile_v in world_map or tile_v in blocked_doors: | ||||
|             return False | ||||
|         x += dx * TILE | ||||
| 
 | ||||
|     # horizontals | ||||
|     y, dy = (ym + TILE, 1) if sin_a >= 0 else (ym, -1) | ||||
|     for i in range(0, int(abs(delta_y)) // TILE): | ||||
|         depth_h = (y - oy) / sin_a | ||||
|         xh = ox + depth_h * cos_a | ||||
|         tile_h = mapping(xh, y + dy) | ||||
|         if tile_h in world_map or tile_h in blocked_doors: | ||||
|             return False | ||||
|         y += dy * TILE | ||||
|     return True | ||||
| 
 | ||||
| 
 | ||||
| class Interaction: | ||||
|     def __init__(self, player, sprites, drawing): | ||||
|         self.player = player | ||||
|         self.sprites = sprites | ||||
|         self.drawing = drawing | ||||
|         self.pain_sound = pygame.mixer.Sound('sound/pain.wav') | ||||
| 
 | ||||
|     def interaction_objects(self): | ||||
|         if self.player.shot and self.drawing.shot_animation_trigger: | ||||
|             for obj in sorted(self.sprites.list_of_objects, key=lambda obj: obj.distance_to_sprite): | ||||
|                 if obj.is_on_fire[1]: | ||||
|                     if obj.is_dead != 'immortal' and not obj.is_dead: | ||||
|                         if ray_casting_npc_player(obj.x, obj.y, | ||||
|                                                   self.sprites.blocked_doors, | ||||
|                                                   world_map, self.player.pos): | ||||
|                             if obj.flag == 'npc': | ||||
|                                 self.pain_sound.play() | ||||
|                             obj.is_dead = True | ||||
|                             obj.blocked = None | ||||
|                             self.drawing.shot_animation_trigger = False | ||||
|                     if obj.flag in {'door_h', 'door_v'} and obj.distance_to_sprite < TILE: | ||||
|                         obj.door_open_trigger = True | ||||
|                         obj.blocked = None | ||||
|                     break | ||||
| 
 | ||||
|     def npc_action(self): | ||||
|         for obj in self.sprites.list_of_objects: | ||||
|             if obj.flag == 'npc' and not obj.is_dead: | ||||
|                 if ray_casting_npc_player(obj.x, obj.y, | ||||
|                                           self.sprites.blocked_doors, | ||||
|                                           world_map, self.player.pos): | ||||
|                     obj.npc_action_trigger = True | ||||
|                     self.npc_move(obj) | ||||
|                 else: | ||||
|                     obj.npc_action_trigger = False | ||||
| 
 | ||||
|     def npc_move(self, obj): | ||||
|         if abs(obj.distance_to_sprite) > TILE: | ||||
|             dx = obj.x - self.player.pos[0] | ||||
|             dy = obj.y - self.player.pos[1] | ||||
|             obj.x = obj.x + 1 if dx < 0 else obj.x - 1 | ||||
|             obj.y = obj.y + 1 if dy < 0 else obj.y - 1 | ||||
| 
 | ||||
|     def clear_world(self): | ||||
|         deleted_objects = self.sprites.list_of_objects[:] | ||||
|         [self.sprites.list_of_objects.remove(obj) for obj in deleted_objects if obj.delete] | ||||
| 
 | ||||
|     def play_music(self): | ||||
|         pygame.mixer.pre_init(44100, -16, 2, 2048) | ||||
|         pygame.mixer.init() | ||||
|         pygame.mixer.music.load('sound/theme.mp3') | ||||
|         pygame.mixer.music.play(10) | ||||
| 
 | ||||
|     def check_win(self): | ||||
|         if not len([obj for obj in self.sprites.list_of_objects if obj.flag == 'npc' and not obj.is_dead]): | ||||
|             pygame.mixer.music.stop() | ||||
|             pygame.mixer.music.load('sound/win.mp3') | ||||
|             pygame.mixer.music.play() | ||||
|             while True: | ||||
|                 for event in pygame.event.get(): | ||||
|                     if event.type == pygame.QUIT: | ||||
|                         exit() | ||||
|                 self.drawing.win() | ||||
|  | @ -0,0 +1,37 @@ | |||
| from player import Player | ||||
| from sprite_objects import * | ||||
| from ray_casting import ray_casting_walls | ||||
| from drawing import Drawing | ||||
| from interaction import Interaction | ||||
| 
 | ||||
| pygame.init() | ||||
| sc = pygame.display.set_mode((WIDTH, HEIGHT)) | ||||
| sc_map = pygame.Surface(MINIMAP_RES) | ||||
| 
 | ||||
| sprites = Sprites() | ||||
| clock = pygame.time.Clock() | ||||
| player = Player(sprites) | ||||
| drawing = Drawing(sc, sc_map, player, clock) | ||||
| interaction = Interaction(player, sprites, drawing) | ||||
| 
 | ||||
| drawing.menu() | ||||
| pygame.mouse.set_visible(False) | ||||
| interaction.play_music() | ||||
| 
 | ||||
| while True: | ||||
| 
 | ||||
|     player.movement() | ||||
|     drawing.background(player.angle) | ||||
|     walls, wall_shot = ray_casting_walls(player, drawing.textures) | ||||
|     drawing.world(walls + [obj.object_locate(player) for obj in sprites.list_of_objects]) | ||||
|     drawing.fps(clock) | ||||
|     drawing.mini_map(player) | ||||
|     drawing.player_weapon([wall_shot, sprites.sprite_shot]) | ||||
| 
 | ||||
|     interaction.interaction_objects() | ||||
|     interaction.npc_action() | ||||
|     interaction.clear_world() | ||||
|     interaction.check_win() | ||||
| 
 | ||||
|     pygame.display.flip() | ||||
|     clock.tick() | ||||
|  | @ -0,0 +1,44 @@ | |||
| from settings import * | ||||
| import pygame | ||||
| from numba.core import types | ||||
| from numba.typed import Dict | ||||
| from numba import int32 | ||||
| 
 | ||||
| _ = False | ||||
| matrix_map = [ | ||||
|     [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1], | ||||
|     [1, _, _, _, _, _, 2, _, _, _, _, _, _, _, _, _, _, 4, _, _, _, _, _, 1], | ||||
|     [1, _, 2, 2, _, _, _, _, _, 2, 2, 2, _, _, _, 3, _, _, _, _, 4, _, _, 1], | ||||
|     [1, _, _, _, _, _, _, _, _, _, _, 2, 2, _, _, _, 3, _, _, _, _, _, _, 1], | ||||
|     [1, _, 2, 2, _, _, _, _, _, _, _, _, 2, _, 4, _, _, 3, _, _, _, 4, _, 1], | ||||
|     [1, _, _, _, _, _, 4, _, _, 2, 2, _, 2, _, _, _, _, _, _, 4, _, _, _, 1], | ||||
|     [1, _, 3, _, _, _, 2, _, _, 2, _, _, 2, _, _, _, 4, _, _, _, _, 4, _, 1], | ||||
|     [1, _, _, 3, _, _, 2, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, 1], | ||||
|     [1, _, 3, _, _, _, _, _, _, _, 3, _, _, 3, 3, _, _, _, _, 3, 3, _, _, 1], | ||||
|     [1, _, 3, _, _, _, 3, 3, _, 3, _, _, _, 3, 3, _, _, _, _, 2, 3, _, _, 1], | ||||
|     [1, _, _, _, _, 3, _, 3, _, _, 3, _, _, _, _, _, _, _, _, _, _, _, _, 1], | ||||
|     [1, _, 4, _, 3, _, _, _, _, 3, _, _, 2, _, _, _, _, _, _, _, _, 2, _, 1], | ||||
|     [1, _, _, _, _, _, 4, _, _, _, _, _, 2, 2, _, _, _, _, _, _, 2, 2, _, 1], | ||||
|     [1, _, _, 4, _, _, _, _, 4, _, _, _, _, 2, 2, 2, 2, 2, 2, 2, 2, _, _, 1], | ||||
|     [1, _, _, _, _, _, _, _, _, _, 4, _, _, _, _, _, _, _, _, _, _, _, _, 1], | ||||
|     [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1] | ||||
| ] | ||||
| 
 | ||||
| WORLD_WIDTH = len(matrix_map[0]) * TILE | ||||
| WORLD_HEIGHT = len(matrix_map) * TILE | ||||
| world_map = Dict.empty(key_type=types.UniTuple(int32, 2), value_type=int32) | ||||
| mini_map = set() | ||||
| collision_walls = [] | ||||
| for j, row in enumerate(matrix_map): | ||||
|     for i, char in enumerate(row): | ||||
|         if char: | ||||
|             mini_map.add((i * MAP_TILE, j * MAP_TILE)) | ||||
|             collision_walls.append(pygame.Rect(i * TILE, j * TILE, TILE, TILE)) | ||||
|             if char == 1: | ||||
|                 world_map[(i * TILE, j * TILE)] = 1 | ||||
|             elif char == 2: | ||||
|                 world_map[(i * TILE, j * TILE)] = 2 | ||||
|             elif char == 3: | ||||
|                 world_map[(i * TILE, j * TILE)] = 3 | ||||
|             elif char == 4: | ||||
|                 world_map[(i * TILE, j * TILE)] = 4 | ||||
|  | @ -0,0 +1,100 @@ | |||
| from settings import * | ||||
| import pygame | ||||
| import math | ||||
| from map import collision_walls | ||||
| 
 | ||||
| class Player: | ||||
|     def __init__(self, sprites): | ||||
|         self.x, self.y = player_pos | ||||
|         self.sprites = sprites | ||||
|         self.angle = player_angle | ||||
|         self.sensitivity = 0.004 | ||||
|         # collision parameters | ||||
|         self.side = 50 | ||||
|         self.rect = pygame.Rect(*player_pos, self.side, self.side) | ||||
|         # weapon | ||||
|         self.shot = False | ||||
| 
 | ||||
|     @property | ||||
|     def pos(self): | ||||
|         return (self.x, self.y) | ||||
| 
 | ||||
|     @property | ||||
|     def collision_list(self): | ||||
|         return collision_walls + [pygame.Rect(*obj.pos, obj.side, obj.side) for obj in | ||||
|                                   self.sprites.list_of_objects if obj.blocked] | ||||
| 
 | ||||
|     def detect_collision(self, dx, dy): | ||||
|         next_rect = self.rect.copy() | ||||
|         next_rect.move_ip(dx, dy) | ||||
|         hit_indexes = next_rect.collidelistall(self.collision_list) | ||||
| 
 | ||||
|         if len(hit_indexes): | ||||
|             delta_x, delta_y = 0, 0 | ||||
|             for hit_index in hit_indexes: | ||||
|                 hit_rect = self.collision_list[hit_index] | ||||
|                 if dx > 0: | ||||
|                     delta_x += next_rect.right - hit_rect.left | ||||
|                 else: | ||||
|                     delta_x += hit_rect.right - next_rect.left | ||||
|                 if dy > 0: | ||||
|                     delta_y += next_rect.bottom - hit_rect.top | ||||
|                 else: | ||||
|                     delta_y += hit_rect.bottom - next_rect.top | ||||
| 
 | ||||
|             if abs(delta_x - delta_y) < 10: | ||||
|                 dx, dy = 0, 0 | ||||
|             elif delta_x > delta_y: | ||||
|                 dy = 0 | ||||
|             elif delta_y > delta_x: | ||||
|                 dx = 0 | ||||
|         self.x += dx | ||||
|         self.y += dy | ||||
| 
 | ||||
|     def movement(self): | ||||
|         self.keys_control() | ||||
|         self.mouse_control() | ||||
|         self.rect.center = self.x, self.y | ||||
|         self.angle %= DOUBLE_PI | ||||
| 
 | ||||
|     def keys_control(self): | ||||
|         sin_a = math.sin(self.angle) | ||||
|         cos_a = math.cos(self.angle) | ||||
|         keys = pygame.key.get_pressed() | ||||
|         if keys[pygame.K_ESCAPE]: | ||||
|             exit() | ||||
| 
 | ||||
|         if keys[pygame.K_w]: | ||||
|             dx = player_speed * cos_a | ||||
|             dy = player_speed * sin_a | ||||
|             self.detect_collision(dx, dy) | ||||
|         if keys[pygame.K_s]: | ||||
|             dx = -player_speed * cos_a | ||||
|             dy = -player_speed * sin_a | ||||
|             self.detect_collision(dx, dy) | ||||
|         if keys[pygame.K_a]: | ||||
|             dx = player_speed * sin_a | ||||
|             dy = -player_speed * cos_a | ||||
|             self.detect_collision(dx, dy) | ||||
|         if keys[pygame.K_d]: | ||||
|             dx = -player_speed * sin_a | ||||
|             dy = player_speed * cos_a | ||||
|             self.detect_collision(dx, dy) | ||||
| 
 | ||||
|         if keys[pygame.K_LEFT]: | ||||
|             self.angle -= 0.02 | ||||
|         if keys[pygame.K_RIGHT]: | ||||
|             self.angle += 0.02 | ||||
| 
 | ||||
|         for event in pygame.event.get(): | ||||
|             if event.type == pygame.QUIT: | ||||
|                 exit() | ||||
|             if event.type == pygame.MOUSEBUTTONDOWN: | ||||
|                 if event.button == 1 and not self.shot: | ||||
|                     self.shot = True | ||||
| 
 | ||||
|     def mouse_control(self): | ||||
|         if pygame.mouse.get_focused(): | ||||
|             difference = pygame.mouse.get_pos()[0] - HALF_WIDTH | ||||
|             pygame.mouse.set_pos((HALF_WIDTH, HALF_HEIGHT)) | ||||
|             self.angle += difference * self.sensitivity | ||||
		Loading…
	
		Reference in New Issue