Better mouse handling + playable on mobile

This commit is contained in:
Evert Prants 2019-11-30 23:49:30 +02:00
parent 546f891acd
commit 9f67f9645e
Signed by: evert
GPG Key ID: 1688DA83D222D0B5
6 changed files with 116 additions and 62 deletions

View File

@ -1,54 +1,6 @@
const canvas = document.createElement('canvas')
const ctx = canvas.getContext('2d')
ctx.mouse = { pos: {} }
canvas.addEventListener('mousemove', (e) => {
let x
let y
if (e.changedTouches) {
let touch = e.changedTouches[0]
if (touch) {
e.pageX = touch.pageX
e.pageY = touch.pageY
}
}
if (e.pageX || e.pageY) {
x = e.pageX
y = e.pageY
} else {
x = e.clientX + document.body.scrollLeft + document.documentElement.scrollLeft
y = e.clientY + document.body.scrollTop + document.documentElement.scrollTop
}
x -= canvas.offsetLeft
y -= canvas.offsetTop
if (ctx.oX && ctx.oY) {
x += ctx.oX
y += ctx.oY
}
ctx.mouse.pos.x = x
ctx.mouse.pos.y = y
}, false)
canvas.addEventListener('mousedown', (e) => {
e.preventDefault()
ctx.mouse['btn' + e.button] = true
})
canvas.addEventListener('mouseup', (e) => {
e.preventDefault()
ctx.mouse['btn' + e.button] = false
})
canvas.addEventListener('contextmenu', (e) => {
e.preventDefault()
})
// Resize the canvas when window is resized
canvas.resizeWorkspace = function () {
canvas.width = window.innerWidth

View File

@ -2,7 +2,7 @@ import { canvas, ctx } from './canvas'
import { Level, Rock, Gold, Diamond, Lootbag, BarrelPiece } from './level'
import { randomi } from './utils'
const MAP_CLEARANCE_PERCENTAGE = 90
const MAP_CLEARANCE_PERCENTAGE = 85
const REWARD_TABLE = {
rock: 16,
@ -21,6 +21,8 @@ export class Game {
this.lastGoal = 0
this.goal = 0
this.pause = false
this.level = null
this.oh = oh
this.gh = gh
@ -101,6 +103,8 @@ export class Game {
ctx.oX = (canvas.width - this.gw) / 2
ctx.oY = (canvas.height - this.gh) / 2
if (this.pause) return
if (this.state === 0 && this.time === 0) {
if (this.score > this.goal) {
this.state = 1
@ -120,6 +124,22 @@ export class Game {
return
}
if (this.state === 2) {
if (ctx.mouse.click['btn0'] && !this._rst) {
this._rst = true
setTimeout(() => {
this._rst = undefined
this.currentLevel = 0
this.score = 0
this.goal = 0
this.lastGoal = 0
this.nextLevel()
this.state = 0
}, 200)
}
return
}
if (this.state !== 0) return
if (this.message) {
if (this.message.time > 0) {
@ -135,7 +155,7 @@ export class Game {
}
tick () {
if (this.state === 0 && this.time > 0) {
if (this.state === 0 && this.time > 0 && !this.pause) {
this.time -= 1
}
}
@ -148,16 +168,6 @@ export class Game {
let s = 'Score: $' + this.score
ctx.fillText(t, ctx.oX + this.gw / 2 - ctx.measureText(t).width / 2, ctx.oY + this.gh / 2 - 15)
ctx.fillText(s, ctx.oX + this.gw / 2 - ctx.measureText(s).width / 2, ctx.oY + this.gh / 2 + 15)
if (ctx.mouse['btn0']) {
setTimeout(() => {
this.currentLevel = 0
this.score = 0
this.goal = 0
this.lastGoal = 0
this.nextLevel()
this.state = 0
}, 500)
}
return
}
@ -191,6 +201,7 @@ export class Game {
ctx.fillText('Goal: $' + this.goal, ctx.oX + 20, ctx.oY + 62)
ctx.fillStyle = '#05ff05'
let time = 'Time: ' + this.time
if (this.pause) time = 'PAUSED'
let ftsize = ctx.measureText(time)
ctx.fillText(time, ctx.oX + this.gw - ftsize.width - 5, ctx.oY + 30)

View File

@ -2,9 +2,11 @@
import { canvas, ctx } from './canvas'
import { Game } from './game'
import { Player } from './player'
import { Mouse } from './mouse'
import { mobile } from './utils'
import RES from './resource'
const GameWidth = 1080
const GameWidth = mobile() ? window.innerWidth : 1080
const GameHeight = 720
let playing = true
@ -21,11 +23,14 @@ function gameLoop () {
playing && requestAnimationFrame(gameLoop)
ctx.fillStyle = '#111'
ctx.fillRect(0, 0, canvas.width, canvas.height)
ctx.mouse.update()
if (ctx.mouse.click['btn2']) game.pause = !game.pause
game.update()
game.draw()
}
function start () {
ctx.mouse = new Mouse()
game.nextLevel()
gameLoop()
setInterval(function () {

82
src/mouse.js Normal file
View File

@ -0,0 +1,82 @@
import { canvas, ctx } from './canvas'
export class Mouse {
constructor () {
this.bindEvents()
this.pos = {}
this.down = {}
this.downLast = {}
this.click = {}
}
handleDn (e) {
e.preventDefault()
let btn = e.button || 0
ctx.mouse.down['btn' + btn] = true
}
handleUp (e) {
e.preventDefault()
let btn = e.button || 0
ctx.mouse.down['btn' + btn] = false
}
handleMove (e) {
let x
let y
if (e.changedTouches) {
let touch = e.changedTouches[0]
if (touch) {
e.pageX = touch.pageX
e.pageY = touch.pageY
}
}
if (e.pageX || e.pageY) {
x = e.pageX
y = e.pageY
} else {
x = e.clientX + document.body.scrollLeft + document.documentElement.scrollLeft
y = e.clientY + document.body.scrollTop + document.documentElement.scrollTop
}
x -= canvas.offsetLeft
y -= canvas.offsetTop
if (ctx.oX && ctx.oY) {
x += ctx.oX
y += ctx.oY
}
ctx.mouse.pos.x = x
ctx.mouse.pos.y = y
}
bindEvents () {
canvas.addEventListener('mousemove', this.handleMove, false)
canvas.addEventListener('mousedown', this.handleDn, false)
canvas.addEventListener('mouseup', this.handleUp, false)
canvas.addEventListener('touchstart', this.handleDn, false)
canvas.addEventListener('touchend', this.handleUp, false)
canvas.addEventListener('touchcancel', this.handleUp, false)
canvas.addEventListener('touchmove', this.handleMove, false)
canvas.addEventListener('contextmenu', (e) => {
e.preventDefault()
}, false)
}
update () {
this.click = {}
for (let i in this.down) {
let dn = this.down[i]
if (!dn && this.downLast[i]) {
this.click[i] = true
}
this.downLast[i] = dn
}
}
}

View File

@ -77,7 +77,7 @@ class Hook extends GameObject {
this.rd = 1
}
if (ctx.mouse['btn0'] && this.d === 0 && !this.obj) {
if (ctx.mouse.down['btn0'] && this.d === 0 && !this.obj) {
this.d = 0
this.md = 1
}

View File

@ -23,3 +23,7 @@ export function intersectRect (r1, r2) {
export function distanceTo (o1, o2) {
return Math.sqrt(Math.pow(o2.x - o1.x, 2) + Math.pow(o2.y - o1.y, 2))
}
export function mobile () {
return /Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(navigator.userAgent)
}