add a basic terrain layout
This commit is contained in:
@@ -333,6 +333,7 @@ export default class Entity {
|
|||||||
|
|
||||||
if (!this.#moving || this.#dest == null) { return false }
|
if (!this.#moving || this.#dest == null) { return false }
|
||||||
|
|
||||||
|
// TODO: bounding boxes to early discard a lot of collidables
|
||||||
const collidables = this.collidables()
|
const collidables = this.collidables()
|
||||||
const fixedDest = SATX.clamp(SATX.fixCollisions(this.#dest, collidables, this.radius), this.game?.width, this.game?.height, this.radius)
|
const fixedDest = SATX.clamp(SATX.fixCollisions(this.#dest, collidables, this.radius), this.game?.width, this.game?.height, this.radius)
|
||||||
|
|
||||||
|
|||||||
+2
-2
@@ -11,12 +11,12 @@ export default class Game {
|
|||||||
averageTick = 0
|
averageTick = 0
|
||||||
currentTick = 0
|
currentTick = 0
|
||||||
entities = []
|
entities = []
|
||||||
height = 5000
|
height = 10000 * 1.6
|
||||||
projectiles = []
|
projectiles = []
|
||||||
secondToSlowestTick = 0
|
secondToSlowestTick = 0
|
||||||
terrains = []
|
terrains = []
|
||||||
tickRate = 30
|
tickRate = 30
|
||||||
width = 5000
|
width = 10000 * 1.6
|
||||||
|
|
||||||
#currentTiming = 0
|
#currentTiming = 0
|
||||||
#eventEmitter = new EventEmitter()
|
#eventEmitter = new EventEmitter()
|
||||||
|
|||||||
+62
-38
@@ -6,6 +6,7 @@ import Game from './game.js'
|
|||||||
import Team from './team.js'
|
import Team from './team.js'
|
||||||
import Template from './template.js'
|
import Template from './template.js'
|
||||||
import Terrain from './terrain.js'
|
import Terrain from './terrain.js'
|
||||||
|
import Level from './level.js'
|
||||||
|
|
||||||
const app = new WebSocketExpress()
|
const app = new WebSocketExpress()
|
||||||
const port = 1280
|
const port = 1280
|
||||||
@@ -15,6 +16,7 @@ app.use('/', express.static('public'))
|
|||||||
app.use('/three/', express.static('node_modules/three'))
|
app.use('/three/', express.static('node_modules/three'))
|
||||||
app.use('/@tweenjs/', express.static('node_modules/@tweenjs'))
|
app.use('/@tweenjs/', express.static('node_modules/@tweenjs'))
|
||||||
app.use('/stats.js/', express.static('node_modules/stats.js'))
|
app.use('/stats.js/', express.static('node_modules/stats.js'))
|
||||||
|
app.use('/tools/', express.static('tools'))
|
||||||
app.use(express.urlencoded({ extended: true }))
|
app.use(express.urlencoded({ extended: true }))
|
||||||
|
|
||||||
app.ws('/ws', async (req, res) => {
|
app.ws('/ws', async (req, res) => {
|
||||||
@@ -74,52 +76,73 @@ function laneScenario() {
|
|||||||
game.spawnEntity(player1)
|
game.spawnEntity(player1)
|
||||||
player1.attackAction(new Vector2(500, 150))
|
player1.attackAction(new Vector2(500, 150))
|
||||||
|
|
||||||
const player2 = new Entity(Template.player({
|
// const player2 = new Entity(Template.player({
|
||||||
id: '2',
|
// id: '2',
|
||||||
spawnPosition: new Vector2(1600, 1800),
|
// spawnPosition: new Vector2(1600, 1800),
|
||||||
team: Team.red,
|
// team: Team.red,
|
||||||
}))
|
// }))
|
||||||
game.spawnEntity(player2)
|
// game.spawnEntity(player2)
|
||||||
player2.attackAction(new Vector2(1600, 1800))
|
// player2.attackAction(new Vector2(1600, 1800))
|
||||||
|
|
||||||
const midWallStart = new Vector2(600, 600)
|
|
||||||
const midWallEnd = new Vector2(1400, 1400)
|
|
||||||
const midWallMiddle = new Vector2(800, 1200)
|
|
||||||
const midWallThickness = midWallEnd.clone().sub(midWallStart).rotateAround(new Vector2(), -Math.PI / 2).normalize().multiplyScalar(50)
|
|
||||||
const midWallPoints = [
|
|
||||||
midWallStart,
|
|
||||||
midWallMiddle,
|
|
||||||
midWallEnd,
|
|
||||||
midWallEnd.clone().add(midWallThickness),
|
|
||||||
midWallMiddle.clone().add(midWallThickness),
|
|
||||||
midWallStart.clone().add(midWallThickness),
|
|
||||||
]
|
|
||||||
|
|
||||||
const midNorthWallOffset = new Vector2(-450, 450)
|
|
||||||
const midNorthWallPoints = midWallPoints.map((p) => p.clone().add(midNorthWallOffset))
|
|
||||||
const midNorthWall = new Terrain(midNorthWallPoints)
|
|
||||||
midNorthWall.id = 'midNorthWall'
|
|
||||||
game.addTerrain(midNorthWall)
|
|
||||||
|
|
||||||
const midSouthWallOffset = new Vector2(50, -50)
|
|
||||||
const midSouthWallPoints = midWallPoints.map((p) => p.clone().add(midSouthWallOffset))
|
|
||||||
const midSouthWall = new Terrain(midSouthWallPoints)
|
|
||||||
midSouthWall.id = 'midSouthWall'
|
|
||||||
game.addTerrain(midSouthWall)
|
|
||||||
|
|
||||||
const gameLogic = function gameLogic() {
|
const gameLogic = function gameLogic() {
|
||||||
const game = this
|
const game = this
|
||||||
|
|
||||||
const blueRoute = [new Vector2(600, 1350), new Vector2(1900, 1900)]
|
const midRoute = [
|
||||||
const redRoute = [new Vector2(600, 1350), new Vector2(100, 100)]
|
new Vector2(1544, 1572),
|
||||||
|
new Vector2(2748, 2792),
|
||||||
|
new Vector2(3628, 3688),
|
||||||
|
new Vector2(4992, 5000),
|
||||||
|
new Vector2(6272, 6188),
|
||||||
|
new Vector2(7252, 7200),
|
||||||
|
new Vector2(8436, 8408),
|
||||||
|
].map((p) => p.multiplyScalar(1.6))
|
||||||
|
|
||||||
|
const topRoute = [
|
||||||
|
new Vector2(868, 1740),
|
||||||
|
new Vector2(856, 3480),
|
||||||
|
new Vector2(808, 5944),
|
||||||
|
new Vector2(816, 7256),
|
||||||
|
new Vector2(976, 7772),
|
||||||
|
new Vector2(1388, 8384),
|
||||||
|
new Vector2(1948, 8940),
|
||||||
|
new Vector2(2392, 9152),
|
||||||
|
new Vector2(4168, 9196),
|
||||||
|
new Vector2(6548, 9168),
|
||||||
|
new Vector2(8288, 9176),
|
||||||
|
].map((p) => p.multiplyScalar(1.6))
|
||||||
|
|
||||||
|
const botRoute = [
|
||||||
|
new Vector2(1704, 812),
|
||||||
|
new Vector2(3460, 828),
|
||||||
|
new Vector2(5804, 768),
|
||||||
|
new Vector2(7332, 844),
|
||||||
|
new Vector2(8052, 1100),
|
||||||
|
new Vector2(8528, 1516),
|
||||||
|
new Vector2(9080, 2208),
|
||||||
|
new Vector2(9224, 2620),
|
||||||
|
new Vector2(9172, 4344),
|
||||||
|
new Vector2(9136, 6752),
|
||||||
|
new Vector2(9136, 8248),
|
||||||
|
].map((p) => p.multiplyScalar(1.6))
|
||||||
|
|
||||||
if ([(0 * game.tickRate), (1 * game.tickRate), (2 * game.tickRate)].includes(game.currentTick % (30 * game.tickRate))) {
|
if ([(0 * game.tickRate), (1 * game.tickRate), (2 * game.tickRate)].includes(game.currentTick % (30 * game.tickRate))) {
|
||||||
game.spawnEntity(new Entity(Template.minion(Team.blue, { ranged: false, route: blueRoute })))
|
game.spawnEntity(new Entity(Template.minion(Team.blue, { ranged: false, route: topRoute })))
|
||||||
game.spawnEntity(new Entity(Template.minion(Team.red, { ranged: false, route: redRoute })))
|
game.spawnEntity(new Entity(Template.minion(Team.blue, { ranged: false, route: midRoute })))
|
||||||
|
game.spawnEntity(new Entity(Template.minion(Team.blue, { ranged: false, route: botRoute })))
|
||||||
|
|
||||||
|
game.spawnEntity(new Entity(Template.minion(Team.red, { ranged: false, route: topRoute.toReversed() })))
|
||||||
|
game.spawnEntity(new Entity(Template.minion(Team.red, { ranged: false, route: midRoute.toReversed() })))
|
||||||
|
game.spawnEntity(new Entity(Template.minion(Team.red, { ranged: false, route: botRoute.toReversed() })))
|
||||||
}
|
}
|
||||||
|
|
||||||
if ([(3 * game.tickRate), (4 * game.tickRate), (5 * game.tickRate)].includes(game.currentTick % (30 * game.tickRate))) {
|
if ([(3 * game.tickRate), (4 * game.tickRate), (5 * game.tickRate)].includes(game.currentTick % (30 * game.tickRate))) {
|
||||||
game.spawnEntity(new Entity(Template.minion(Team.blue, { ranged: true, route: blueRoute })))
|
game.spawnEntity(new Entity(Template.minion(Team.blue, { ranged: true, route: topRoute })))
|
||||||
game.spawnEntity(new Entity(Template.minion(Team.red, { ranged: true, route: redRoute })))
|
game.spawnEntity(new Entity(Template.minion(Team.blue, { ranged: true, route: midRoute })))
|
||||||
|
game.spawnEntity(new Entity(Template.minion(Team.blue, { ranged: true, route: botRoute })))
|
||||||
|
|
||||||
|
game.spawnEntity(new Entity(Template.minion(Team.red, { ranged: true, route: topRoute.toReversed() })))
|
||||||
|
game.spawnEntity(new Entity(Template.minion(Team.red, { ranged: true, route: midRoute.toReversed() })))
|
||||||
|
game.spawnEntity(new Entity(Template.minion(Team.red, { ranged: true, route: botRoute.toReversed() })))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
game.logic = gameLogic
|
game.logic = gameLogic
|
||||||
@@ -128,6 +151,7 @@ function laneScenario() {
|
|||||||
app.listen(port, () => {
|
app.listen(port, () => {
|
||||||
console.log(`Server started! Visit http://localhost:${port}`)
|
console.log(`Server started! Visit http://localhost:${port}`)
|
||||||
|
|
||||||
|
Level.terrains.map((points) => new Terrain(points.map((p) => p.multiplyScalar(1.6)))).forEach((terrain) => game.addTerrain(terrain))
|
||||||
laneScenario()
|
laneScenario()
|
||||||
|
|
||||||
game.start()
|
game.start()
|
||||||
|
|||||||
+2133
File diff suppressed because it is too large
Load Diff
+1
-1
@@ -9,7 +9,7 @@ export default class Template {
|
|||||||
height: options.ranged ? 40 : 38,
|
height: options.ranged ? 40 : 38,
|
||||||
logic: this.#minionLogic(options.route),
|
logic: this.#minionLogic(options.route),
|
||||||
maxHealth: options.ranged ? 300 : 450,
|
maxHealth: options.ranged ? 300 : 450,
|
||||||
position: team == Team.blue ? new Vector2(200, 200) : new Vector2(1800, 1800),
|
position: options.route?.at(0) ?? new Vector2(0, 0),
|
||||||
radius: 48,
|
radius: 48,
|
||||||
speed: 325,
|
speed: 325,
|
||||||
team,
|
team,
|
||||||
|
|||||||
@@ -0,0 +1,92 @@
|
|||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<title>Terrain Creator</title>
|
||||||
|
<style>
|
||||||
|
* {
|
||||||
|
box-sizing: border-box;
|
||||||
|
}
|
||||||
|
|
||||||
|
html, body {
|
||||||
|
background-color: black;
|
||||||
|
font-family: sans-serif;
|
||||||
|
}
|
||||||
|
|
||||||
|
html {
|
||||||
|
padding: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
body {
|
||||||
|
margin: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
#map {
|
||||||
|
background-color: white;
|
||||||
|
background-image: url('./background.png');
|
||||||
|
background-size: cover;
|
||||||
|
}
|
||||||
|
|
||||||
|
.point {
|
||||||
|
position: absolute;
|
||||||
|
border-radius: 50%;
|
||||||
|
margin-top: -5px;
|
||||||
|
margin-left: -5px;
|
||||||
|
width: 10px;
|
||||||
|
height: 10px;
|
||||||
|
background-color: red;
|
||||||
|
border: 1px solid white;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<div id="map"></div>
|
||||||
|
<script>
|
||||||
|
var width = null
|
||||||
|
var height = null
|
||||||
|
var scale = null
|
||||||
|
var points = []
|
||||||
|
|
||||||
|
window.addEventListener('load', () => {
|
||||||
|
const params = Object.fromEntries(new URLSearchParams(window.location.search).entries())
|
||||||
|
width = params.width
|
||||||
|
height = params.height
|
||||||
|
scale = params.scale
|
||||||
|
if (width == null) {
|
||||||
|
width = prompt('Width: ')
|
||||||
|
}
|
||||||
|
if (height == null) {
|
||||||
|
height = prompt('Height: ')
|
||||||
|
}
|
||||||
|
if (scale == null) {
|
||||||
|
scale = prompt('Scale: ')
|
||||||
|
}
|
||||||
|
|
||||||
|
const map = document.getElementById('map')
|
||||||
|
map.style.width = `${width / scale}px`
|
||||||
|
map.style.height = `${height / scale}px`
|
||||||
|
|
||||||
|
map.addEventListener('contextmenu', (event) => event.preventDefault())
|
||||||
|
map.addEventListener('mousedown', (event) => {
|
||||||
|
if (event.button == 2) {
|
||||||
|
console.log(`\n\n[\n` + points.map((p) => ` new Vector2(${p.x}, ${p.y}),`).join(`\n`) + `\n],\n`)
|
||||||
|
points = []
|
||||||
|
map.innerHTML = ''
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if (event.button == 0) {
|
||||||
|
const x = Math.floor(event.pageX * scale)
|
||||||
|
const y = Math.floor(height - (event.pageY * scale))
|
||||||
|
points.push({ x, y })
|
||||||
|
|
||||||
|
const point = document.createElement('div')
|
||||||
|
point.classList.add('point')
|
||||||
|
point.style.left = event.pageX
|
||||||
|
point.style.top = event.pageY
|
||||||
|
map.appendChild(point)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
})
|
||||||
|
})
|
||||||
|
</script>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
Reference in New Issue
Block a user