add visualRadius

This commit is contained in:
2025-01-17 17:51:00 +09:00
parent a44693aa5d
commit 80ccb92815
6 changed files with 76 additions and 59 deletions
+28 -14
View File
@@ -10,18 +10,21 @@ const backgroundColor = new THREE.Color().setHex(0x112233)
scene.background = backgroundColor
renderer.setSize(window.innerWidth, window.innerHeight)
renderer.setAnimationLoop(render)
camera.position.set(5, -12, 10)
camera.rotation.set((60 / 180) * Math.PI, 0, 0)
camera.position.set(5, -12, 20)
// camera.position.set(5, -12, 10)
camera.rotation.set((56 / 180) * Math.PI, 0, 0)
camera.layers.enable(1)
camera.layers.enable(2)
const entityMaterial = new THREE.MeshToonMaterial({ color: 0xffffff })
const projectileMaterial = new THREE.MeshToonMaterial({ color: 0xff00ff })
const projectileMaterial = new THREE.MeshToonMaterial({ color: 0xcccccc })
const terrainMaterial = new THREE.MeshToonMaterial({ color: 0xffd700 })
const opacity = 0.3
const teamMaterials = {
blue: new THREE.MeshToonMaterial({ color: 0x4444ff }),
neutral: new THREE.MeshToonMaterial({ color: 0x22dd22 }),
red: new THREE.MeshToonMaterial({ color: 0xff4444 }),
blue: new THREE.MeshToonMaterial({ color: 0x4444ff, transparent: true, opacity }),
neutral: new THREE.MeshToonMaterial({ color: 0x22dd22, transparent: true, opacity }),
red: new THREE.MeshToonMaterial({ color: 0xff4444, transparent: true, opacity }),
projectile: new THREE.MeshToonMaterial({ color: 0xff00ff, transparent: true, opacity }),
}
const minimapCamera = new THREE.OrthographicCamera(-10, 10, 10, -10)
@@ -41,11 +44,11 @@ const material = new THREE.MeshToonMaterial({ color: 0x115011 })
const ground = new THREE.Mesh(geometry, material)
scene.add(ground)
const ambientLight = new THREE.AmbientLight(0x404040)
const ambientLight = new THREE.AmbientLight(0x404040, 10)
scene.add(ambientLight)
const directionalLight = new THREE.DirectionalLight(0xffffff, 2.5)
directionalLight.position.set(-0.3, 0.1, 1)
directionalLight.position.set(-0.5, -0.05, 1)
directionalLight.power = 3000
scene.add(directionalLight)
@@ -74,11 +77,12 @@ function followCamera() {
if (entity == null) { return }
const offsetX = 0
const offsetY = -16.5
const offsetY = -28
const distanceX = Math.abs((entity.position.x + offsetX) - camera.position.x)
const distanceY = Math.abs((entity.position.y + offsetY) - camera.position.y)
camera.position.z = 20
if (distanceX > 0.01) {
if (entity.position.x + offsetX > camera.position.x) {
camera.position.x += cameraSpeed * distanceX
@@ -118,7 +122,7 @@ function cameraMovement() {
else if (keysDown.ArrowDown) { camera.position.y -= cameraSpeed }
if (keysDown.Space) {
camera.position.set(entities['1'].position.x, entities['1'].position.y - 17, 10)
camera.position.set(entities[playerId].position.x, entities[playerId].position.y - 28, 20)
}
}
@@ -177,7 +181,7 @@ function connectWebSocket() {
entity = entities[e.id]
}
else {
entity = new THREE.Mesh(new THREE.CylinderGeometry(e.radius / 100, e.radius / 100, e.height / 50), entityMaterial)
entity = new THREE.Mesh(new THREE.CylinderGeometry(e.visualRadius / 100, e.visualRadius / 100, e.height / 50), entityMaterial)
entity.rotation.x = Math.PI / 2
entity.userData.type = 'entity'
entity.userData.id = e.id
@@ -199,8 +203,9 @@ function connectWebSocket() {
const teamMaterial = teamMaterials[e.team]
const teamMarker = new THREE.Mesh(new THREE.CylinderGeometry((e.radius + 2) / 100, (e.radius + 2) / 100, 1), teamMaterial)
teamMarker.scale.y = e.height / 400
teamMarker.position.y = (e.height / 800) - (e.height / 100)
const teamMarkerSize = 4000
teamMarker.scale.y = e.height / teamMarkerSize
teamMarker.position.y = (e.height / (teamMarkerSize * 2)) - (e.height / 100)
entity.rotation.x = Math.PI / 2
entity.add(teamMarker)
@@ -234,13 +239,22 @@ function connectWebSocket() {
projectile = projectiles[p.id]
}
else {
projectile = new THREE.Mesh(new THREE.SphereGeometry(p.radius / 100), projectileMaterial)
projectile = new THREE.Mesh(new THREE.SphereGeometry(p.visualRadius / 100), projectileMaterial)
projectile.userData.type = 'projectile'
projectile.userData.id = p.id
projectile.position.set(p.position.x / 100, p.position.y / 100, p.height / 100)
projectile.layers.set(2)
scene.add(projectile)
const teamMaterial = teamMaterials['projectile']
const teamMarker = new THREE.Mesh(new THREE.CylinderGeometry((p.radius) / 100, (p.radius) / 100, 1), teamMaterial)
const teamMarkerSize = 4000
teamMarker.scale.y = p.height / teamMarkerSize
teamMarker.position.y = (p.height / (teamMarkerSize * 2)) - (p.height / 100)
projectile.rotation.x = Math.PI / 2
projectile.layers.set(2)
projectile.add(teamMarker)
projectiles[p.id] = projectile
}
+13 -11
View File
@@ -30,9 +30,10 @@ export default class Ability {
name: 'Straight Shot',
castTime: 0.25,
cooldown: 1,
damage: 10,
damage: 83,
radius: 60,
range: 1200,
visualRadius: 20,
speed: 2000,
effect: function straightShotEffect(caster, cursor) {
const ability = this
@@ -47,6 +48,7 @@ export default class Ability {
position: caster.position.clone(),
radius: ability.radius,
speed: ability.speed,
visualRadius: ability.visualRadius,
})
projectile.destination = caster.position.clone().add(cursor.clone().sub(caster.position).normalize().multiplyScalar(ability.range + caster.radius))
@@ -58,13 +60,13 @@ export default class Ability {
static rangedAttack = new Ability({
id: 'ranged_attack',
name: 'Ranged Attack',
castTime: 0.25,
cooldown: 1.25,
damage: 25,
castTime: (1.6 * 0.18839),
cooldown: 1.6,
damage: 60,
moveCancelable: true,
radius: 5,
range: 500,
speed: 600,
speed: 2000,
effect: function rangedAttackEffect(caster, cursor) {
const ability = this
const target = caster.closestTargetTo(cursor, ability.range)
@@ -110,11 +112,11 @@ export default class Ability {
static shieldThrow = new Ability({
id: 'shield_throw',
name: 'Shield Throw',
castTime: 0.15,
castTime: 0.25,
cooldown: 5,
radius: 20,
range: 1000,
speed: 2000,
radius: 110,
range: 1025,
speed: 2400,
effect: function shieldThrowEffect(caster, cursor) {
const ability = this
const shieldThrowReturn = function shieldThrowReturn(projectile, homingTarget) {
@@ -146,9 +148,9 @@ export default class Ability {
static blink = new Ability({
id: 'blink',
name: 'Blink',
castTime: 1,
castTime: 0.25,
cooldown: 2,
range: 400,
range: 475,
effect: function blinkEffect(caster, cursor) {
const ability = this
const direction = cursor.clone().sub(caster.position)
+6 -1
View File
@@ -13,11 +13,12 @@ export default class Entity {
health = null
height = 40
maxHealth = 1
memory = {} // TODO: WARNING: currently only used for minions (code smell?)
memory = {}
position = null
radius = 0
speed = 400
team = Team.neutral
visualRadius = null
#attacking = false
#dest = null
@@ -39,6 +40,9 @@ export default class Entity {
if (this.health == null) {
this.health = this.maxHealth
}
if (this.visualRadius == null) {
this.visualRadius = this.radius
}
}
get destination() { return this.#dest }
@@ -90,6 +94,7 @@ export default class Entity {
castAction(slot, cursor, halt = false) {
const ability = this.abilities[slot]
if (ability == null) { return }
if (this.casting != null) {
const abilityBeingCasted = this.casting.ability
+18 -30
View File
@@ -37,24 +37,29 @@ app.ws('/ws', async (req, res) => {
console.log(message)
}
let delay = 0
// if(message.id == '1') {
// delay = 45
// }
if (message.action == 'attack') {
entity.attackAction(new Vector2(message.x, message.y))
setTimeout(() => entity.attackAction(new Vector2(message.x, message.y)), delay)
}
if (message.action == 'cast') {
entity.castAction(message.slot, new Vector2(message.x, message.y))
setTimeout(() => entity.castAction(message.slot, new Vector2(message.x, message.y)), delay)
}
if (message.action == 'halt') {
entity.haltAction()
setTimeout(() => entity.haltAction(), delay)
}
if (message.action == 'stop') {
entity.stopAction()
setTimeout(() => entity.stopAction(), delay)
}
if (message.action == 'move') {
entity.moveAction(new Vector2(message.x, message.y))
setTimeout(() => entity.moveAction(new Vector2(message.x, message.y)), delay)
}
})
})
@@ -68,13 +73,13 @@ function laneScenario() {
game.spawnEntity(player1)
player1.attackAction(new Vector2(500, 150))
// const player2 = new Entity(Template.player({
// id: '2',
// spawnPosition: new Vector2(1600, 1800),
// team: Team.red,
// }))
// game.spawnEntity(player2)
// player2.attackAction(new Vector2(1600, 1800))
const player2 = new Entity(Template.player({
id: '2',
spawnPosition: new Vector2(1600, 1800),
team: Team.red,
}))
game.spawnEntity(player2)
player2.attackAction(new Vector2(1600, 1800))
const midWallStart = new Vector2(600, 600)
const midWallEnd = new Vector2(1400, 1400)
@@ -116,24 +121,7 @@ function laneScenario() {
game.spawnEntity(new Entity(Template.minion(Team.red, { ranged: true, route: redRoute })))
}
}
// game.logic = gameLogic
// const uBottomPoints = [
// midSouthWallPoints.at(0).clone().sub(midWallThickness),
// midSouthWallPoints.at(1).clone().sub(midWallThickness),
// midNorthWallPoints.at(-2).clone().add(midWallThickness),
// midNorthWallPoints.at(-1).clone().add(midWallThickness),
// ]
// const uBottom = new Terrain(uBottomPoints)
// uBottom.id = 'uBottom'
// game.addTerrain(uBottom)
const minion = new Entity({...Template.minion(Team.red, { ranged: true }), logic: null})
minion.teleport(new Vector2(850, 250))
game.spawnEntity(minion)
player1.stopAction()
player1.castAction(1, new Vector2(850, 250))
game.logic = gameLogic
}
app.listen(port, () => {
+7 -1
View File
@@ -6,12 +6,13 @@ export default class Projectile {
id = crypto.randomUUID()
after = null
height = 50
memory = {} // TODO: WARNING: currently only used for hit detection (code smell?)
memory = {}
onCollide = null
owner = null
position = new Vector2()
radius = 5
speed = 1000
visualRadius = null
#dest = null
#homingTarget = null
@@ -28,6 +29,9 @@ export default class Projectile {
constructor(options = {}) {
Object.entries(options).forEach(([key, value]) => this[key] = value)
if (this.visualRadius == null) {
this.visualRadius = this.radius
}
}
checkCollisions(collider) {
@@ -72,6 +76,8 @@ export default class Projectile {
}
#move() {
if (this.destination == null) { return }
const speed = (this.speed / (this.game?.tickBudget ?? 1000))
const prevPos = this.position.clone()
if (this.position.distanceTo(this.destination) < speed) {
+3 -1
View File
@@ -10,9 +10,10 @@ export default class Template {
logic: this.#minionLogic(options.route),
maxHealth: options.ranged ? 300 : 450,
position: team == Team.blue ? new Vector2(200, 200) : new Vector2(1800, 1800),
radius: options.ranged ? 46 : 48,
radius: 48,
speed: 325,
team,
visualRadius: options.ranged ? 36 : 38,
}
}
@@ -29,6 +30,7 @@ export default class Template {
maxHealth: 600,
spawnPosition: new Vector2(500, 150),
radius: 65,
visualRadius: 40,
...overrides,
}
}