velocity based movement
This commit is contained in:
parent
2bd5838065
commit
76f6f2f9d5
1 changed files with 58 additions and 103 deletions
161
src/Field.vue
161
src/Field.vue
|
@ -1,20 +1,23 @@
|
||||||
<template>
|
<template>
|
||||||
<div id="field">
|
<div id="field">
|
||||||
<input v-keep-focussed type="text"
|
<input v-keep-focussed type="text"
|
||||||
@keydown.down="goDown($event)"
|
@keydown.up="player_push_y = -8"
|
||||||
@keydown.up="goUp($event)"
|
@keydown.down="player_push_y = 8"
|
||||||
@keydown.right="goRight($event)"
|
@keydown.right="player_push_x = 8"
|
||||||
@keydown.left="goLeft($event)"
|
@keydown.left="player_push_x = -8"
|
||||||
@keydown.space="jump($event)"
|
@keyup.up="player_push_y = 0"
|
||||||
|
@keyup.down="player_push_y = 0"
|
||||||
|
@keyup.right="player_push_x = 0"
|
||||||
|
@keyup.left="player_push_x = 0"
|
||||||
/>
|
/>
|
||||||
<mountain-background :x="x + 65536" />
|
<mountain-background :x="128 + x / 8" />
|
||||||
<div id="wrap" :style="{transform: `translate(${translate_x}px, ${translate_y}px)`}">
|
<div id="wrap" :style="{transform: `translate(${tx}px, ${ty}px)`}">
|
||||||
<template v-for="(row, y) in rows">
|
<template v-for="row in rows">
|
||||||
<div v-for="(block, x) in row" class="block" :class="[block.type]" :data-x="x" :data-y="y" />
|
<div v-for="block in row" class="block" :class="[block.type]" />
|
||||||
</template>
|
</template>
|
||||||
</div>
|
</div>
|
||||||
<div id="player" :class="[player_direction]" :data-x="player_x" :data-y="player_y" />
|
<div id="player" :class="[player_direction]" :data-x="player_x" :data-y="player_y" />
|
||||||
<div id="level-indicator">x:{{ x }}, y:{{ y }}</div>
|
<div id="level-indicator">x:{{ floorX }}, y:{{ floorY }}</div>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
|
@ -24,12 +27,11 @@ import Level from './level'
|
||||||
import MountainBackground from './Background'
|
import MountainBackground from './Background'
|
||||||
|
|
||||||
const BLOCK_SIZE = 32
|
const BLOCK_SIZE = 32
|
||||||
const WIDTH = 32
|
const RECIPROCAL = 1 / BLOCK_SIZE
|
||||||
const HEIGHT = 32
|
const PLAYER_X = ~~(BLOCK_SIZE / 2) + 1
|
||||||
const PLAYER_X = ~~(WIDTH / 2) + 1
|
const PLAYER_Y = BLOCK_SIZE - 15
|
||||||
const PLAYER_Y = HEIGHT - 15
|
|
||||||
const PLAYER_MAX_VELOCITY = 32
|
const PLAYER_MAX_VELOCITY = 32
|
||||||
const level = new Level(WIDTH + 2, HEIGHT + 2)
|
const level = new Level(BLOCK_SIZE + 2, BLOCK_SIZE + 2)
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: 'field',
|
name: 'field',
|
||||||
|
@ -38,111 +40,64 @@ export default {
|
||||||
return {
|
return {
|
||||||
x: 0,
|
x: 0,
|
||||||
y: 0,
|
y: 0,
|
||||||
// transform: translate(x,y); max 32px, then this.x++ / this.y++
|
|
||||||
translate_x: 0,
|
|
||||||
translate_y: 0,
|
|
||||||
player_x: PLAYER_X,
|
player_x: PLAYER_X,
|
||||||
player_y: PLAYER_Y,
|
player_y: PLAYER_Y,
|
||||||
player_direction: 'left',
|
player_direction: 'left',
|
||||||
|
player_push_x: 0,
|
||||||
|
player_push_y: 0,
|
||||||
player_velocity_x: 0,
|
player_velocity_x: 0,
|
||||||
player_velocity_y: 0,
|
player_velocity_y: 0,
|
||||||
drag: 1
|
moving: false
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
mounted () {
|
mounted () {
|
||||||
this.mindTheGap()
|
this.player_velocity_y = 8
|
||||||
|
this.move()
|
||||||
},
|
},
|
||||||
watch: {
|
watch: {
|
||||||
player_velocity_x: throttle(function (v) {
|
player_push_x (px) {
|
||||||
if (!v) return // zero velocity is not interesting
|
if (px === 0) this.player_velocity_x = 0
|
||||||
|
else this.player_velocity_x = px
|
||||||
// calculate with positive values but remember negative velocity
|
|
||||||
const sign = v < 0 ? -1 : 1
|
|
||||||
v *= sign
|
|
||||||
|
|
||||||
if (v > 8) v = 8
|
|
||||||
|
|
||||||
v -= this.drag
|
|
||||||
if (v < 0) v = 0
|
|
||||||
else v *= sign // back to original sign
|
|
||||||
this.player_velocity_x = v
|
|
||||||
this.translate_x += v
|
|
||||||
console.log(v)
|
|
||||||
}, 100),
|
|
||||||
translate_x (tx) {
|
|
||||||
this.x += Math.floor(tx / BLOCK_SIZE)
|
|
||||||
this.translate_x = tx % BLOCK_SIZE
|
|
||||||
},
|
},
|
||||||
player_velocity_y (velocity_y) {
|
player_push_y (py) {
|
||||||
//if (!velocity_y) return // zero velocity is not interesting
|
if (py === 0) this.player_velocity_y = 8
|
||||||
return // TODO
|
else this.player_velocity_y = py
|
||||||
|
|
||||||
if (velocity_y < 0) {
|
|
||||||
if (!this.blockBelowPlayer.walkable) this.player_velocity_y = 0
|
|
||||||
else if (this.translate_y > -BLOCK_SIZE) this.translate_y += velocity_y
|
|
||||||
else {
|
|
||||||
this.translate_y = 0
|
|
||||||
this.y++
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
if (!this.blockAbovePlayer.walkable) this.player_velocity_y = 0
|
|
||||||
else if (this.translate_y < BLOCK_SIZE) this.translate_y += velocity_y
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
},
|
},
|
||||||
computed: {
|
computed: {
|
||||||
rows () {
|
blockAtPlayer () { return this.rows[PLAYER_Y][PLAYER_X] },
|
||||||
return level.grid(this.x, this.y)
|
blockLeftOfPlayer () { return this.rows[PLAYER_Y][PLAYER_X - 1] },
|
||||||
},
|
blockRightOfPlayer () { return this.rows[PLAYER_Y][PLAYER_X + 1] },
|
||||||
blockAtPlayer () {
|
blockAbovePlayer () { return this.rows[PLAYER_Y - 1][PLAYER_X] },
|
||||||
return this.rows[PLAYER_Y][PLAYER_X]
|
blockBelowPlayer () { return this.rows[PLAYER_Y + 1][PLAYER_X] },
|
||||||
},
|
blockedUp () { return this.cornerY && !this.blockAbovePlayer.walkable },
|
||||||
blockLeftOfPlayer () {
|
blockedDown () { return this.cornerY && !this.blockBelowPlayer.walkable },
|
||||||
return this.rows[PLAYER_Y][PLAYER_X - 1]
|
blockedLeft () { return this.cornerX && !this.blockLeftOfPlayer.walkable },
|
||||||
},
|
blockedRight () { return this.cornerX && !this.blockRightOfPlayer.walkable },
|
||||||
blockRightOfPlayer () {
|
cornerX () { return this.x === ~~this.x }, // cornering a block
|
||||||
return this.rows[PLAYER_Y][PLAYER_X + 1]
|
cornerY () { return this.y === ~~this.y },
|
||||||
},
|
floorX () { return Math.floor(this.x) },
|
||||||
blockAbovePlayer () {
|
floorY () { return Math.floor(this.y) },
|
||||||
return this.rows[PLAYER_Y - 1][PLAYER_X]
|
tx () { return (this.x - this.floorX) * -BLOCK_SIZE },
|
||||||
},
|
ty () { return (this.y - this.floorY) * -BLOCK_SIZE },
|
||||||
blockBelowPlayer () {
|
rows () { return level.grid(this.floorX, this.floorY) }
|
||||||
return this.rows[PLAYER_Y + 1][PLAYER_X]
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
goDown (ev) {
|
move () {
|
||||||
// TODO: this.player_direction = 'down'
|
const x = this.x
|
||||||
if (this.blockBelowPlayer.walkable) this.player_velocity_y -= 8
|
const y = this.y
|
||||||
this.mindTheGap()
|
let vx = this.player_velocity_x * RECIPROCAL
|
||||||
|
let vy = this.player_velocity_y * RECIPROCAL
|
||||||
|
|
||||||
|
if (vx > 0 && this.blockedRight) vx = 0
|
||||||
|
if (vx < 0 && this.blockedLeft) vx = 0
|
||||||
|
if (vy > 0 && this.blockedDown) vy = 0
|
||||||
|
if (vy < 0 && this.blockedUp) vy = 0
|
||||||
|
|
||||||
|
this.x += vx
|
||||||
|
this.y += vy
|
||||||
|
this.moving = setTimeout(() => this.move(), 50)
|
||||||
},
|
},
|
||||||
goUp (ev) {
|
|
||||||
// TODO: this.player_direction = 'up'
|
|
||||||
if (this.blockAtPlayer.climbable) this.player_velocity_y += 8
|
|
||||||
},
|
|
||||||
goRight: throttle(function (ev) {
|
|
||||||
if (this.blockRightOfPlayer.walkable) {
|
|
||||||
this.player_velocity_x -= 4
|
|
||||||
}
|
|
||||||
}, 10),
|
|
||||||
goLeft: throttle(function (ev) {
|
|
||||||
if (this.blockLeftOfPlayer.walkable) {
|
|
||||||
this.player_velocity_x += 4
|
|
||||||
}
|
|
||||||
}, 10),
|
|
||||||
jump (ev) {
|
|
||||||
if (this.blockAbovePlayer.walkable) {
|
|
||||||
this.player_velocity_y += 64
|
|
||||||
this.mindTheGap()
|
|
||||||
}
|
|
||||||
},
|
|
||||||
mindTheGap () {
|
|
||||||
const below = this.blockBelowPlayer
|
|
||||||
if (below.walkable && !below.climbable) {
|
|
||||||
this.player_velocity_y -= 8
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
Loading…
Reference in a new issue