initiates central physics handling
This commit is contained in:
parent
7c6e716875
commit
59ac454bc5
5 changed files with 90 additions and 60 deletions
|
@ -19,7 +19,9 @@ export default {
|
||||||
|
|
||||||
<style>
|
<style>
|
||||||
html,body,#app {
|
html,body,#app {
|
||||||
display: block;
|
display: flex;
|
||||||
|
flex-flow: column nowrap;
|
||||||
|
justify-content: center;
|
||||||
width: 100vw;
|
width: 100vw;
|
||||||
height: 100vh;
|
height: 100vh;
|
||||||
background: black;
|
background: black;
|
||||||
|
@ -27,5 +29,4 @@ html,body,#app {
|
||||||
padding: 0;
|
padding: 0;
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
}
|
}
|
||||||
|
|
||||||
</style>
|
</style>
|
||||||
|
|
|
@ -4,6 +4,7 @@
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
import solarQuartet from './solar-quartet'
|
import solarQuartet from './solar-quartet'
|
||||||
|
import { BLOCK_SIZE, STAGE_WIDTH, STAGE_HEIGHT } from './level/def'
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: 'background',
|
name: 'background',
|
||||||
|
@ -21,18 +22,16 @@ export default {
|
||||||
time () { this.refresh() }
|
time () { this.refresh() }
|
||||||
},
|
},
|
||||||
mounted () {
|
mounted () {
|
||||||
const canvasSize = 512
|
|
||||||
const godraysSize = 128
|
|
||||||
const canvas = this.$refs.canvas
|
const canvas = this.$refs.canvas
|
||||||
const godraysCanvas = document.createElement('canvas')
|
const godraysCanvas = document.createElement('canvas')
|
||||||
canvas.width = canvasSize
|
canvas.width = STAGE_WIDTH * BLOCK_SIZE
|
||||||
canvas.height = canvasSize
|
canvas.height = STAGE_HEIGHT * BLOCK_SIZE
|
||||||
godraysCanvas.width = godraysSize
|
godraysCanvas.width = ~~(canvas.width / 8.0)
|
||||||
godraysCanvas.height = godraysSize
|
godraysCanvas.height = ~~(canvas.height / 8.0)
|
||||||
this.redraw = solarQuartet.bind(
|
this.redraw = solarQuartet.bind(
|
||||||
null,
|
null,
|
||||||
canvas, canvas.getContext('2d'), canvasSize, canvasSize,
|
canvas, canvas.getContext('2d'), ~~(canvas.width / 2.0), ~~(canvas.height / 2.0),
|
||||||
godraysCanvas, godraysCanvas.getContext('2d'), godraysSize, godraysSize,
|
godraysCanvas, godraysCanvas.getContext('2d'), godraysCanvas.width, godraysCanvas.height,
|
||||||
)
|
)
|
||||||
this.refresh()
|
this.refresh()
|
||||||
},
|
},
|
||||||
|
@ -65,8 +64,8 @@ export default {
|
||||||
<style>
|
<style>
|
||||||
#background {
|
#background {
|
||||||
display: block;
|
display: block;
|
||||||
width: 100%;
|
width: var(--field-width);
|
||||||
height: 100%;
|
height: var(--field-height);
|
||||||
object-fit: contain;
|
object-fit: contain;
|
||||||
background: black;
|
background: black;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,13 +1,14 @@
|
||||||
<template>
|
<template>
|
||||||
<div id="field" :class="daytimeClass">
|
<div id="field" :class="daytimeClass">
|
||||||
<input v-keep-focussed type="text"
|
<input v-keep-focussed type="text"
|
||||||
@keydown.up="jump = jump || !blocked.down ? jump : 20"
|
@keydown.up="inputY = -1"
|
||||||
@keydown.down="moveTo = 'down'"
|
@keydown.down="inputY = 1"
|
||||||
@keydown.right="moveTo = 'right'"
|
@keydown.right="inputX = -1"
|
||||||
@keydown.left="moveTo = 'left'"
|
@keydown.left="inputX = 1"
|
||||||
@keyup.down="moveTo = null"
|
@keyup.up="inputY = inputY === -1 ? 0 : 1"
|
||||||
@keyup.right="moveTo = null"
|
@keyup.down="inputY = inputY === 1 ? 0 : 1"
|
||||||
@keyup.left="moveTo = null"
|
@keyup.right="inputX = inputX === -1 ? 0 : 1"
|
||||||
|
@keyup.left="inputX = inputX === 1 ? 0: -1"
|
||||||
@keypress.p="togglePause"
|
@keypress.p="togglePause"
|
||||||
@keydown.space="digging = true"
|
@keydown.space="digging = true"
|
||||||
@keyup.space="digging = false"
|
@keyup.space="digging = false"
|
||||||
|
@ -18,7 +19,7 @@
|
||||||
<div v-for="(block, x) in row" class="block" :class="[block.type]" />
|
<div v-for="(block, x) in row" class="block" :class="[block.type]" />
|
||||||
</template>
|
</template>
|
||||||
</div>
|
</div>
|
||||||
<div id="player" :class="[playerDirection]" />
|
<div id="player" :class="[player.direction]" />
|
||||||
<div id="level-indicator">
|
<div id="level-indicator">
|
||||||
x:{{ floorX }}, y:{{ floorY }}
|
x:{{ floorX }}, y:{{ floorY }}
|
||||||
<template v-if="moving !== false">({{clock}})</template>
|
<template v-if="moving !== false">({{clock}})</template>
|
||||||
|
@ -29,36 +30,39 @@
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
// import throttle from 'lodash/throttle'
|
// import throttle from 'lodash/throttle'
|
||||||
import Level from './level'
|
|
||||||
import MountainBackground from './Background'
|
import MountainBackground from './Background'
|
||||||
|
import Level from './level'
|
||||||
|
import { Moveable } from './physics'
|
||||||
|
import {
|
||||||
|
BLOCK_SIZE,
|
||||||
|
RECIPROCAL,
|
||||||
|
STAGE_WIDTH,
|
||||||
|
STAGE_HEIGHT,
|
||||||
|
PLAYER_X,
|
||||||
|
PLAYER_Y
|
||||||
|
} from './level/def'
|
||||||
|
|
||||||
const BLOCK_SIZE = 32
|
const level = new Level(STAGE_WIDTH + 2, STAGE_HEIGHT + 2)
|
||||||
const RECIPROCAL = 1 / BLOCK_SIZE
|
const player = new Moveable(PLAYER_X, PLAYER_Y)
|
||||||
const PLAYER_X = ~~(BLOCK_SIZE / 2) + 1
|
|
||||||
const PLAYER_Y = BLOCK_SIZE - 15
|
|
||||||
const PLAYER_MAX_VELOCITY = 32
|
|
||||||
const level = new Level(BLOCK_SIZE + 2, BLOCK_SIZE + 2)
|
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: 'field',
|
name: 'field',
|
||||||
components: { MountainBackground },
|
components: { MountainBackground },
|
||||||
data () {
|
data () {
|
||||||
return {
|
return {
|
||||||
|
player,
|
||||||
x: 0,
|
x: 0,
|
||||||
y: 0,
|
y: 12,
|
||||||
playerDirection: 'left',
|
inputX: 0,
|
||||||
playerVelocityX: 0,
|
inputY: 0,
|
||||||
playerVelocityY: 8,
|
time: 250,
|
||||||
moveTo: null,
|
|
||||||
jump: 0,
|
|
||||||
digging: false,
|
|
||||||
gravity: 8.0 / 20,
|
|
||||||
moving: false,
|
moving: false,
|
||||||
time: 250
|
lastTick: 0
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
mounted () {
|
mounted () {
|
||||||
this.move()
|
this.lastTick = performance.now()
|
||||||
|
this.move(this.lastTick)
|
||||||
},
|
},
|
||||||
computed: {
|
computed: {
|
||||||
rows () { return level.grid(this.floorX, this.floorY) },
|
rows () { return level.grid(this.floorX, this.floorY) },
|
||||||
|
@ -110,28 +114,21 @@ export default {
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
move () {
|
move (thisTick) {
|
||||||
|
this.moving = requestAnimationFrame(this.move)
|
||||||
|
|
||||||
|
// keep roughly 20 fps
|
||||||
|
if (thisTick - this.lastTick < 50) return
|
||||||
|
|
||||||
// set time of day in ticks
|
// set time of day in ticks
|
||||||
this.time = (this.time + 0.1) % 1000
|
this.time = (this.time + 0.1) % 1000
|
||||||
|
|
||||||
const x = this.x
|
const player = this.player
|
||||||
const y = this.y
|
const x = player.x
|
||||||
|
const y = player.y
|
||||||
|
|
||||||
if (this.moveTo !== null) this.playerDirection = this.moveTo
|
let dx = player.vx * player.dir * RECIPROCAL
|
||||||
|
let dy = player.vy * RECIPROCAL
|
||||||
if (this.moveTo === 'right') {
|
|
||||||
this.playerVelocityX = 8
|
|
||||||
} else if (this.moveTo === 'left') {
|
|
||||||
this.playerVelocityX = -8
|
|
||||||
} else {
|
|
||||||
this.playerVelocityX = 0
|
|
||||||
}
|
|
||||||
|
|
||||||
// this.player_velocity_y += this.gravity
|
|
||||||
let dx = this.playerVelocityX * RECIPROCAL
|
|
||||||
let dy = (this.playerVelocityY - this.jump) * RECIPROCAL
|
|
||||||
|
|
||||||
if (this.jump > 0) this.jump -= 2
|
|
||||||
|
|
||||||
// don't walk / fall into blocks
|
// don't walk / fall into blocks
|
||||||
if (dx > 0 && this.blocked.right) dx = 0
|
if (dx > 0 && this.blocked.right) dx = 0
|
||||||
|
@ -140,14 +137,14 @@ export default {
|
||||||
if (dy < 0 && this.blocked.up) dy = 0
|
if (dy < 0 && this.blocked.up) dy = 0
|
||||||
|
|
||||||
// don't walk, work!
|
// don't walk, work!
|
||||||
if (!this.jump && this.digging) {
|
if (!this.inputY && this.digging) {
|
||||||
dx = 0
|
dx = 0
|
||||||
this.dig()
|
this.dig()
|
||||||
}
|
}
|
||||||
|
|
||||||
this.x += dx
|
this.x += dx
|
||||||
this.y += dy
|
this.y += dy
|
||||||
this.moving = setTimeout(() => this.move(), 64) // roughly every 4 frames
|
this.lastTick = thisTick
|
||||||
},
|
},
|
||||||
dig () {
|
dig () {
|
||||||
console.log('dig', this.playerDirection, this.surroundings[this.playerDirection])
|
console.log('dig', this.playerDirection, this.surroundings[this.playerDirection])
|
||||||
|
@ -163,10 +160,9 @@ export default {
|
||||||
},
|
},
|
||||||
togglePause () {
|
togglePause () {
|
||||||
if (this.moving === false) { // is paused
|
if (this.moving === false) { // is paused
|
||||||
this.moving = true // avoid (unlikely) race condition
|
|
||||||
this.move()
|
this.move()
|
||||||
} else {
|
} else {
|
||||||
clearTimeout(this.moving)
|
cancelAnimationFrame(this.moving)
|
||||||
this.moving = false
|
this.moving = false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -179,7 +175,7 @@ export default {
|
||||||
:root {
|
:root {
|
||||||
--block-size: 32px;
|
--block-size: 32px;
|
||||||
--field-width: 1024px;
|
--field-width: 1024px;
|
||||||
--field-height: 1024px;
|
--field-height: 576px;
|
||||||
--spare-blocks: 2;
|
--spare-blocks: 2;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,3 +1,15 @@
|
||||||
|
export const BLOCK_SIZE = 32 // each block is 32̨̣̌̇x32 pixel in size and equals 1m
|
||||||
|
export const RECIPROCAL = 1 / BLOCK_SIZE
|
||||||
|
|
||||||
|
export const STAGE_WIDTH = 32 // 32*32 = 1024 pixel wide stage
|
||||||
|
export const STAGE_HEIGHT = ~~(STAGE_WIDTH * 0.5625) // 16:9 😎
|
||||||
|
|
||||||
|
// the player position is fixed to the middle of the x axis
|
||||||
|
export const PLAYER_X = ~~(STAGE_WIDTH / 2) + 1
|
||||||
|
export const PLAYER_Y = ~~(STAGE_HEIGHT * 0.5) // fall from the center
|
||||||
|
|
||||||
|
export const GRAVITY = 10 // blocks per second
|
||||||
|
|
||||||
export const type = {
|
export const type = {
|
||||||
air: {type: 'air', hp: Infinity, walkable: true},
|
air: {type: 'air', hp: Infinity, walkable: true},
|
||||||
grass: {type: 'grass', hp: 1, walkable: false},
|
grass: {type: 'grass', hp: 1, walkable: false},
|
||||||
|
|
22
src/physics.js
Normal file
22
src/physics.js
Normal file
|
@ -0,0 +1,22 @@
|
||||||
|
import { GRAVITY } from './level/def'
|
||||||
|
|
||||||
|
/** physics gets input like
|
||||||
|
instance of Moveable,
|
||||||
|
position: [x, y],
|
||||||
|
surroundings: [top, right, bottom, left] where each is a block type
|
||||||
|
and updates the Moveable instance values accordingly
|
||||||
|
*/
|
||||||
|
|
||||||
|
export class Moveable {
|
||||||
|
constructor (x, y, direction = 1) {
|
||||||
|
this.x = x
|
||||||
|
this.y = y
|
||||||
|
this.dir = direction
|
||||||
|
this.vx = 0
|
||||||
|
this.vy = 0
|
||||||
|
}
|
||||||
|
|
||||||
|
get direction () {
|
||||||
|
return this.dir > 0 ? 'left' : 'right'
|
||||||
|
}
|
||||||
|
}
|
Loading…
Add table
Reference in a new issue