Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[SOK-40] Game map #23

Merged
merged 2 commits into from
Oct 11, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions packages/client/src/assets/images/sprites/wall.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
8 changes: 4 additions & 4 deletions packages/client/src/components/Game/Game.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ const livesUse = 3
export const Game: React.FC = () => {
const canvasRef = useRef<HTMLCanvasElement | null>(null)
const playerRef = useRef(PLAYER_DEFAULT_PARAMS)
const enemiesRef = useRef(initializeEnemies(5))
const enemiesRef = useRef(initializeEnemies())
const obstaclesRef = useRef<Obstacle[]>(initializeObstacle())
const livesRef = useRef(livesUse)
const [gameStarted, setGameStarted] = useState(false)
Expand Down Expand Up @@ -86,9 +86,9 @@ export const Game: React.FC = () => {
setIsPaused(false)
isPausedRef.current = false
setIsGameOver(false)
livesRef.current = livesUse
playerRef.current = PLAYER_DEFAULT_PARAMS
enemiesRef.current = initializeEnemies(5)
livesRef.current = 3
playerRef.current = { ...PLAYER_DEFAULT_PARAMS }
enemiesRef.current = initializeEnemies()
}

return (
Expand Down
33 changes: 15 additions & 18 deletions packages/client/src/components/Game/enemy.tsx
Original file line number Diff line number Diff line change
@@ -1,22 +1,19 @@
import { getRandomEdgePosition } from './utils'
import React from 'react'
import { Enemy, Player } from '@/components/Game/gameTypes'

export const initializeEnemies = (numberOfEnemies: number) => {
const initialEnemies: Enemy[] = []
for (let i = 0; i < numberOfEnemies; i++) {
// количество врагов
const { x, y } = getRandomEdgePosition(800, 600)
const enemy: Enemy = {
x,
y,
width: 30,
height: 30,
speed: 1,
direction: { x: 0, y: 0 },
}
initialEnemies.push(enemy)
}
return initialEnemies as Enemy[]
const enemyParams = {
width: 70,
height: 70,
speed: 0,
direction: { x: 0, y: 0 },
}

export const initializeEnemies = (): Enemy[] => {
return [
{ ...enemyParams, x: 50, y: 55 },
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Возможно лучше дефолтны объект создать, и копировать его, подменяя позицию.

Что-то типо:

{ ...enemyParams, x: 1, y: 2}

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Да, не подумал об этом, так действительно лучше

{ ...enemyParams, x: 320, y: 250 },
{ ...enemyParams, x: 715, y: 60 },
]
}

export const updateEnemyPositions = (
Expand All @@ -39,5 +36,5 @@ export const updateEnemyPositions = (
}

export const respawnEnemies = (enemiesRef: React.MutableRefObject<Enemy[]>) => {
enemiesRef.current = initializeEnemies(5)
enemiesRef.current = initializeEnemies()
}
32 changes: 18 additions & 14 deletions packages/client/src/components/Game/gameLoop.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { HandlePlayerHit, resetPlayerPosition } from './player'
import { updateEnemyPositions, respawnEnemies } from './enemy'
import { HandlePlayerHit } from './player'
import { updateEnemyPositions } from './enemy'
import { clearCanvas, drawPlayer, drawEnemies, drawObstacles } from './utils'
import { Enemy, Obstacle, Player } from '@/components/Game/gameTypes'
import { detectEnemyCollision } from '@/components/Game/collision'
Expand Down Expand Up @@ -31,16 +31,20 @@ export const gameLoop = (
drawPlayer(context, playerRef.current)
drawEnemies(context, enemiesRef.current)

// Проверка на столкновения между игроком и врагами
enemiesRef.current.forEach(enemy => {
if (detectEnemyCollision(playerRef.current, enemy)) {
// Обработка столкновения: уменьшаем жизни
HandlePlayerHit(
livesRef,
handleGameOver,
() => resetPlayerPosition(playerRef),
() => respawnEnemies(enemiesRef)
)
}
})
const collidedEnemy = enemiesRef.current.find(enemy =>
detectEnemyCollision(playerRef.current, enemy)
)

if (collidedEnemy) {
HandlePlayerHit(
livesRef,
handleGameOver,
() => {
playerRef.current = { ...playerRef.current, x: 400, y: 560 }
},
() => {
enemiesRef.current = enemiesRef.current.map(e => ({ ...e }))
}
)
}
}
35 changes: 27 additions & 8 deletions packages/client/src/components/Game/obstacle.tsx
Original file line number Diff line number Diff line change
@@ -1,12 +1,31 @@
import { Obstacle } from '@/components/Game/gameTypes'
import { getRandomEdgePosition } from '@/components/Game/utils'

export const initializeObstacle = (): Obstacle[] => {
const obstacles: Obstacle[] = []
for (let i = 0; i < 10; i++) {
const { x, y } = getRandomEdgePosition(800, 600)
const obstacle: Obstacle = { x, y, width: 50, height: 50 }
obstacles.push(obstacle)
}
return obstacles
return [
{ x: 0, y: 0, width: 120, height: 50 },
{ x: 200, y: 0, width: 70, height: 50 },
{ x: 350, y: 0, width: 70, height: 50 },
{ x: 500, y: 0, width: 120, height: 50 },
{ x: 700, y: 0, width: 100, height: 50 },

{ x: 0, y: 130, width: 50, height: 120 },
{ x: 130, y: 130, width: 50, height: 70 },
{ x: 260, y: 130, width: 50, height: 200 },
{ x: 390, y: 130, width: 50, height: 70 },
{ x: 520, y: 130, width: 50, height: 120 },
{ x: 650, y: 130, width: 50, height: 125 },

{ x: 0, y: 330, width: 120, height: 50 },
{ x: 200, y: 330, width: 150, height: 50 },
{ x: 350, y: 330, width: 70, height: 50 },
{ x: 500, y: 330, width: 120, height: 50 },
{ x: 700, y: 330, width: 100, height: 100 },

{ x: 0, y: 460, width: 50, height: 140 },
{ x: 130, y: 530, width: 50, height: 70 },
{ x: 260, y: 480, width: 50, height: 120 },
{ x: 390, y: 460, width: 50, height: 70 },
{ x: 520, y: 490, width: 50, height: 120 },
{ x: 650, y: 480, width: 50, height: 120 },
]
}
11 changes: 5 additions & 6 deletions packages/client/src/components/Game/player.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import { Player } from '@/components/Game/gameTypes'

export const PLAYER_DEFAULT_PARAMS = {
x: 400,
y: 300,
y: 560,
width: 70,
height: 70,
speed: 2,
Expand Down Expand Up @@ -31,13 +31,12 @@ export const HandlePlayerHit = (
resetPlayerPosition: () => void,
respawnEnemies: () => void
) => {
const newLives = livesRef.current - 1
livesRef.current -= 1

if (newLives <= 0) {
if (livesRef.current <= 0) {
handleGameOver()
} else {
livesRef.current = newLives
resetPlayerPosition() // Сбрасываем позицию игрока
respawnEnemies() // Респавн врагов
resetPlayerPosition()
respawnEnemies()
}
}
17 changes: 16 additions & 1 deletion packages/client/src/components/Game/utils.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,22 @@ export const drawObstacles = (
context: CanvasRenderingContext2D,
obstacles: Obstacle[]
) => {
const SPRITE_SIZE = 50

obstacles.forEach(obstacle => {
context.drawImage(wallSprite, obstacle.x, obstacle.y)
const horizontalCount = Math.ceil(obstacle.width / SPRITE_SIZE)
const verticalCount = Math.ceil(obstacle.height / SPRITE_SIZE)

Array.from({ length: horizontalCount }).forEach((_, i) => {
Array.from({ length: verticalCount }).forEach((_, j) => {
const x = obstacle.x + i * SPRITE_SIZE
const y = obstacle.y + j * SPRITE_SIZE

const width = Math.min(SPRITE_SIZE, obstacle.width - i * SPRITE_SIZE)
const height = Math.min(SPRITE_SIZE, obstacle.height - j * SPRITE_SIZE)

context.drawImage(wallSprite, 0, 0, width, height, x, y, width, height)
})
})
})
}
Loading