Skip to content

Commit

Permalink
Week 2 - 1: broken into 4 files
Browse files Browse the repository at this point in the history
  • Loading branch information
cent5 committed Jun 25, 2022
1 parent c675241 commit 9137c51
Show file tree
Hide file tree
Showing 4 changed files with 213 additions and 179 deletions.
45 changes: 45 additions & 0 deletions src/common.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
import enum

import pygame
from pygame.color import Color
from pygame.surface import Surface
from utils import scale_image

SCREEN_WIDTH: int = 1280
SCREEN_HEIGHT: int = 768

WHITE: Color = Color(255, 255, 255)
RED: Color = Color(255, 0, 0) # Màu Đỏ
BLUE: Color = Color(0, 0, 255) # Màu Xanh

FPS: int = 30 # Số cảnh mỗi giây (frame per second)

# Fonts
pygame.font.init()
FREESANSBOLD_24 = pygame.font.Font("freesansbold.ttf", 24)
FREESANSBOLD_48 = pygame.font.Font("freesansbold.ttf", 48)

# Hình nền:
BACKGROUND_SPRITE: Surface = pygame.image.load("assets/background.png")
BACKGROUND_SPRITE.set_alpha(128)
BACKGROUND_SPRITE = pygame.transform.scale(BACKGROUND_SPRITE, [SCREEN_WIDTH, SCREEN_HEIGHT])

# Game Entities Sprites
PLAYER_SPRITE: Surface = scale_image(pygame.image.load("assets/player.png"), 0.2)
ROBOT_SPRITE: Surface = scale_image(pygame.image.load("assets/robot.png"), 0.08)
DIAMOND_BLUE_SPRITE: Surface = scale_image(pygame.image.load("assets/diamond_blue.png"), 0.02)
DIAMOND_RED_SPRITE: Surface = scale_image(pygame.image.load("assets/diamond_red.png"), 0.02)
TO_MO_SPRITE: Surface = scale_image(pygame.image.load("assets/to_mo.png"), 0.2)


class EntityType(enum.Enum):
PLAYER = enum.auto()
ROBOT = enum.auto()
DIAMOND_BLUE = enum.auto()
DIAMOND_RED = enum.auto()


class GameState(enum.Enum):
RUNNING = enum.auto()
WON = enum.auto()
LOST = enum.auto()
129 changes: 129 additions & 0 deletions src/entities.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,129 @@
from typing import Optional

import pygame
from pygame.surface import Surface

from common import (
BLUE,
FREESANSBOLD_24,
FREESANSBOLD_48,
RED,
SCREEN_HEIGHT,
SCREEN_WIDTH,
GameState,
)


class Player:
def __init__(self, x: int, y: int, image: Surface) -> None:
self.x = x
self.y = y
self.image = image

def _move(self, dx: int, dy: int):
new_x = self.x + dx
new_y = self.y + dy

if 0 < new_x < SCREEN_WIDTH - self.image.get_width():
self.x = new_x
if 0 < new_y < SCREEN_HEIGHT - self.image.get_height():
self.y = new_y

def update(self) -> None:
pressed = pygame.key.get_pressed()
if pressed[pygame.K_UP] or pressed[pygame.K_w]:
self._move(0, -10)
if pressed[pygame.K_DOWN] or pressed[pygame.K_s]:
self._move(0, 10)
if pressed[pygame.K_LEFT] or pressed[pygame.K_a]:
self._move(-10, 0)
if pressed[pygame.K_RIGHT] or pressed[pygame.K_d]:
self._move(10, 0)

def render(self, screen: Surface) -> None:
screen.blit(self.image, (self.x, self.y))


class Robot:
def __init__(self, x: int, y: int, image: Surface, x_heading: int, y_heading: int) -> None:
self.x = x
self.y = y
self.image = image
self.x_heading = x_heading
self.y_heading = y_heading

def update(self):
self.x = self.x + self.x_heading
self.y = self.y + self.y_heading

if self.x > SCREEN_WIDTH - self.image.get_width():
self.x_heading = -self.x_heading
if self.x < 0:
self.x_heading = -self.x_heading
if self.y > SCREEN_HEIGHT - self.image.get_height():
self.y_heading = -self.y_heading
if self.y < 0:
self.y_heading = -self.y_heading

def render(self, screen: Surface) -> None:
screen.blit(self.image, (self.x, self.y))


class NPC:
def __init__(self, x: int, y: int, image: Surface) -> None:
self.x = x
self.y = y
self.image = image

def render(self, screen: Surface) -> None:
screen.blit(self.image, (self.x, self.y))


class GameItem:
def __init__(self, x: int, y: int, image: Surface) -> None:
self.x = x
self.y = y
self.image = image
self.hidden = False

def set_hidden(self):
self.hidden = True

def render(self, screen: Surface) -> None:
if not self.hidden:
screen.blit(self.image, (self.x, self.y))


class GameStatus:
def __init__(self) -> None:
self.score: int = 0
self.state: GameState = GameState.RUNNING

def update_state(self, state: GameState) -> None:
self.state = state

def update_score(self, delta: int) -> None:
self.score += delta

def render(self, screen: Surface) -> None:
# Score Text Render on Top Left Corner
score_text = FREESANSBOLD_24.render("Score: %d" % self.score, True, BLUE)
screen.blit(score_text, (10, 10))

# Status Text Render in Middle of Screen
status_text = None
if self.state == GameState.WON:
status_text = FREESANSBOLD_48.render("YOU WON!!", True, RED)
elif self.state == GameState.LOST:
status_text = FREESANSBOLD_48.render("YOU LOST!!", True, RED)

if status_text:
position = (
SCREEN_WIDTH // 2 - status_text.get_width() // 2,
SCREEN_HEIGHT // 2 - status_text.get_height() // 2,
)

screen.blit(status_text, position)

def is_running(self):
return self.state == GameState.RUNNING
196 changes: 17 additions & 179 deletions src/main.py
Original file line number Diff line number Diff line change
@@ -1,188 +1,26 @@
import enum
from typing import List, Optional, Tuple
from typing import List

import pygame
from pygame import Color
from entities import NPC, GameItem, GameStatus, Player, Robot
from pygame.surface import Surface
from utils import overlap

from common import (
BACKGROUND_SPRITE,
DIAMOND_BLUE_SPRITE,
DIAMOND_RED_SPRITE,
FPS,
PLAYER_SPRITE,
ROBOT_SPRITE,
SCREEN_HEIGHT,
SCREEN_WIDTH,
TO_MO_SPRITE,
WHITE,
GameState,
)

pygame.init()

SCREEN_WIDTH: int = 1280
SCREEN_HEIGHT: int = 768

WHITE: Color = Color(255, 255, 255)
RED: Color = Color(255, 0, 0) # Màu Đỏ
BLUE: Color = Color(0, 0, 255) # Màu Xanh

FPS: int = 30 # Số cảnh mỗi giây (frame per second)

# Fonts
pygame.font.init()
FREESANSBOLD_24 = pygame.font.Font("freesansbold.ttf", 24)
FREESANSBOLD_48 = pygame.font.Font("freesansbold.ttf", 48)

# Hình nền:
BACKGROUND_SPRITE: Surface = pygame.image.load("assets/background.png")
BACKGROUND_SPRITE.set_alpha(128)
BACKGROUND_SPRITE = pygame.transform.scale(BACKGROUND_SPRITE, [SCREEN_WIDTH, SCREEN_HEIGHT])


# Hàm tiện ích (utility)
def scale_image(image: Surface, scale: float) -> Surface:
"""Resizes image by a factor of input arg `scale`."""
new_dimension: Tuple[int, int] = (
int(image.get_width() * scale),
int(image.get_height() * scale),
)
return pygame.transform.scale(image, new_dimension)


# Game Entities Sprites
PLAYER_SPRITE: Surface = scale_image(pygame.image.load("assets/player.png"), 0.2)
ROBOT_SPRITE: Surface = scale_image(pygame.image.load("assets/robot.png"), 0.08)
DIAMOND_BLUE_SPRITE: Surface = scale_image(pygame.image.load("assets/diamond_blue.png"), 0.02)
DIAMOND_RED_SPRITE: Surface = scale_image(pygame.image.load("assets/diamond_red.png"), 0.02)
TO_MO_SPRITE: Surface = scale_image(pygame.image.load("assets/to_mo.png"), 0.2)


# Hàm tiện ích (utility)
def overlap(x1: int, y1: int, image1: Surface, x2: int, y2: int, image2: Surface) -> bool:
"""Returns True if 2 items overlap."""
mask1 = pygame.mask.from_surface(image1)
mask2 = pygame.mask.from_surface(image2)
offset_x = x2 - x1
offset_y = y2 - y1
return bool(mask1.overlap(mask2, (offset_x, offset_y)))


class EntityType(enum.Enum):
PLAYER = enum.auto()
ROBOT = enum.auto()
DIAMOND_BLUE = enum.auto()
DIAMOND_RED = enum.auto()


class GameState(enum.Enum):
RUNNING = enum.auto()
WON = enum.auto()
LOST = enum.auto()


class Player:
def __init__(self, x: int, y: int, image: Surface) -> None:
self.x = x
self.y = y
self.image = image

def _move(self, dx: int, dy: int):
new_x = self.x + dx
new_y = self.y + dy

if 0 < new_x < SCREEN_WIDTH - self.image.get_width():
self.x = new_x
if 0 < new_y < SCREEN_HEIGHT - self.image.get_height():
self.y = new_y

def update(self) -> None:
pressed = pygame.key.get_pressed()
if pressed[pygame.K_UP] or pressed[pygame.K_w]:
self._move(0, -10)
if pressed[pygame.K_DOWN] or pressed[pygame.K_s]:
self._move(0, 10)
if pressed[pygame.K_LEFT] or pressed[pygame.K_a]:
self._move(-10, 0)
if pressed[pygame.K_RIGHT] or pressed[pygame.K_d]:
self._move(10, 0)

def render(self, screen: Surface) -> None:
screen.blit(self.image, (self.x, self.y))


class Robot:
def __init__(self, x: int, y: int, image: Surface, x_heading: int, y_heading: int) -> None:
self.x = x
self.y = y
self.image = image
self.x_heading = x_heading
self.y_heading = y_heading

def update(self):
self.x = self.x + self.x_heading
self.y = self.y + self.y_heading

if self.x > SCREEN_WIDTH - self.image.get_width():
self.x_heading = -self.x_heading
if self.x < 0:
self.x_heading = -self.x_heading
if self.y > SCREEN_HEIGHT - self.image.get_height():
self.y_heading = -self.y_heading
if self.y < 0:
self.y_heading = -self.y_heading

def render(self, screen: Surface) -> None:
screen.blit(self.image, (self.x, self.y))


class NPC:
def __init__(self, x: int, y: int, image: Surface) -> None:
self.x = x
self.y = y
self.image = image

def render(self, screen: Surface) -> None:
screen.blit(self.image, (self.x, self.y))


class GameItem:
def __init__(self, x: int, y: int, image: Surface) -> None:
self.x = x
self.y = y
self.image = image
self.hidden = False

def set_hidden(self):
self.hidden = True

def render(self, screen: Surface) -> None:
if not self.hidden:
screen.blit(self.image, (self.x, self.y))


class GameStatus:
def __init__(self) -> None:
self.score: int = 0
self.state: GameState = GameState.RUNNING

def update_state(self, state: GameState) -> None:
self.state = state

def update_score(self, delta: int) -> None:
self.score += delta

def render(self, screen: Surface) -> None:
# Score Text Render on Top Left Corner
score_text = FREESANSBOLD_24.render("Score: %d" % self.score, True, BLUE)
screen.blit(score_text, (10, 10))

# Status Text Render in Middle of Screen
status_text = None
if self.state == GameState.WON:
status_text = FREESANSBOLD_48.render("YOU WON!!", True, RED)
elif self.state == GameState.LOST:
status_text = FREESANSBOLD_48.render("YOU LOST!!", True, RED)

if status_text:
position = (
SCREEN_WIDTH // 2 - status_text.get_width() // 2,
SCREEN_HEIGHT // 2 - status_text.get_height() // 2,
)

screen.blit(status_text, position)

def is_running(self):
return self.state == GameState.RUNNING


screen: Surface = pygame.display.set_mode([SCREEN_WIDTH, SCREEN_HEIGHT])
clock = pygame.time.Clock()

Expand Down
Loading

0 comments on commit 9137c51

Please sign in to comment.