first commit

This commit is contained in:
Florian Sylvain
2026-06-16 02:18:42 +02:00
commit 786fc9b293
2 changed files with 294 additions and 0 deletions
+12
View File
@@ -0,0 +1,12 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>game js</title>
</head>
<body>
<canvas></canvas>
<script src="main.js"></script>
</body>
</html>
+282
View File
@@ -0,0 +1,282 @@
"use strict"
class Clock {
constructor() {
this.currentFrametime = 0
this.currentFps = 0
this.frames = 0
this.timeSpan = 0
}
update(deltaT) {
if (typeof deltaT !== 'number') return;
this.timeSpan += deltaT
this.frames++
if (this.timeSpan >= 500) {
this.currentFrametime = this.timeSpan / this.frames
this.currentFps = 1000 / this.currentFrametime
this.timeSpan = 0
this.frames = 0
}
}
}
class UI {
constructor(context, clock) {
this.context = context
this.context.font = "32px monospace"
this.clock = clock
}
draw() {
this.context.fillStyle = '#FFF'
this.context.fillText(`frametime: ${this.clock.currentFrametime.toFixed(1)} ms`, 10, 32);
this.context.fillText(`fps: ${Math.round(this.clock.currentFps)}`, 10, 64);
}
}
class Vector2 {
constructor(x, y) {
this.x = x
this.y = y
}
length() {
return Math.sqrt((this.x * this.x) + (this.y * this.y))
}
normalize() {
const magnitude = this.length()
if (magnitude === 0) return;
this.x /= magnitude
this.y /= magnitude
}
add(vector2) {
this.x += vector2.x
this.y += vector2.y
}
multiply(scalar) {
this.x *= scalar
this.y *= scalar
}
dot(vector2) {
return vector2.x * this.x + vector2.y * this.y
}
}
class Weapon {
constructor(player, canvas) {
this.player = player
this.angle = 0
this.mousePosition = new Vector2(0, 0)
this.rect = canvas.getBoundingClientRect()
this.width = 10
this.height = 50
document.addEventListener("mousemove", (event) => {
this.mousePosition.x = event.clientX - this.rect.left
this.mousePosition.y = event.clientY - this.rect.top
})
}
get pivotX() {
return this.player.position.x + (this.player.width / 2)
}
get pivotY() {
return this.player.position.y + (this.player.height / 2)
}
update(deltaT, camera) {
const worldMouseX = (this.mousePosition.x / camera.zoom) + camera.x
const worldMouseY = (this.mousePosition.y / camera.zoom) + camera.y
const dx = worldMouseX - this.pivotX
const dy = worldMouseY - this.pivotY
this.angle = Math.atan2(dy, dx) - Math.PI / 2
}
draw(context) {
context.save()
context.translate(this.pivotX, this.pivotY)
context.rotate(this.angle)
context.fillStyle = '#F00'
context.fillRect(-(this.width / 2), 0, this.width, this.height)
context.restore()
}
}
class Player {
constructor(position) {
this.position = position
this.direction = new Vector2(0, 0)
this.velocity = new Vector2(0, 0)
this.speed = 500
this.width = 50
this.height = 50
this.keys = {
w: false,
a: false,
s: false,
d: false
}
document.addEventListener('keydown', (event) => {
if (this.keys[event.key] !== undefined) {
this.keys[event.key] = true
}
})
document.addEventListener('keyup', (event) => {
if (this.keys[event.key] !== undefined) {
this.keys[event.key] = false
}
})
}
update(deltaT) {
this.direction.x = 0
this.direction.y = 0
if (this.keys.w) this.direction.y -= 1
if (this.keys.a) this.direction.x -= 1
if (this.keys.s) this.direction.y += 1
if (this.keys.d) this.direction.x += 1
this.direction.normalize()
this.velocity.x = this.direction.x * this.speed
this.velocity.y = this.direction.y * this.speed
this.velocity.multiply(deltaT)
this.position.add(this.velocity)
}
draw(context) {
context.fillStyle = '#00A'
context.fillRect(this.position.x, this.position.y, this.width, this.height)
}
}
class Camera {
constructor(viewportWidth, viewportHeight) {
this.x = 0
this.y = 0
this.zoom = 2.0
this.viewportWidth = viewportWidth
this.viewportHeight = viewportHeight
}
follow(target) {
this.x = target.x - (this.viewportWidth / 2) / this.zoom
this.y = target.y - (this.viewportHeight / 2) / this.zoom
}
begin(context) {
context.save()
context.scale(this.zoom, this.zoom)
context.translate(-this.x, -this.y)
}
end(context) {
context.restore()
}
}
class Game {
constructor (canvas, context) {
this._WIDTH = 1920
this._HEIGHT = 1080
this.isRunning = true
this.lastTime = undefined
this.deltaTime = undefined
this.context = context
this.canvas = canvas
this.canvas.width = this._WIDTH
this.canvas.height = this._HEIGHT
this.clock = new Clock()
this.UI = new UI(this.context, this.clock)
this.player = new Player(new Vector2(200, 200))
this.weapon = new Weapon(this.player, this.canvas)
this.camera = new Camera(this._WIDTH, this._HEIGHT)
}
update() {
this.clock.update(this.deltaTime)
const deltaTInSeconds = this.deltaTime / 1000
if (!isNaN(deltaTInSeconds)) {
this.player.update(deltaTInSeconds)
this.weapon.update(deltaTInSeconds, this.camera)
}
this.camera.follow(new Vector2(this.player.position.x + 25, this.player.position.y + 25))
}
clear() {
this.context.fillStyle = "#777"
this.context.fillRect(0, 0, this._WIDTH, this._HEIGHT)
}
draw() {
this.clear()
this.camera.begin(this.context)
this.context.fillStyle = '#BB0022'
const c = 20
for (let x = 100; x < this._WIDTH - 100; x += c) {
for (let y = 100; y < this._HEIGHT - 100; y += c) {
this.context.fillRect(x, y, c/2, c/2)
}
}
this.player.draw(this.context)
this.weapon.draw(this.context)
this.camera.end(this.context)
this.UI.draw()
}
run(timeSpan) {
if (this.lastTime === undefined) {
this.lastTime = timeSpan
} else {
this.deltaTime = timeSpan - this.lastTime
this.lastTime = timeSpan
}
this.update()
this.draw()
if (!this.isRunning) return;
requestAnimationFrame((d) => this.run(d))
}
}
const canvas = document.querySelector("canvas")
const context = canvas.getContext("2d")
const game = new Game(canvas, context)
game.run()