Make 3D controls

This commit is contained in:
HF 2020-02-01 15:33:46 +01:00
parent 737a84df2d
commit 0a54b96535
9 changed files with 314 additions and 67 deletions

View File

@ -135,6 +135,13 @@ export function setWait(wait: ?number): Action {
};
}
export function setMobile(mobile: boolean): Action {
return {
type: 'SET_MOBILE',
mobile,
};
}
export function selectColor(color: ColorIndex): Action {
return {
type: 'SELECT_COLOR',

View File

@ -31,6 +31,7 @@ export type Action =
| { type: 'SET_HOVER', hover: Cell }
| { type: 'UNSET_HOVER' }
| { type: 'SET_WAIT', wait: ?number }
| { type: 'SET_MOBILE', mobile: boolean }
| { type: 'COOLDOWN_END' }
| { type: 'COOLDOWN_SET', coolDown: number }
| { type: 'SELECT_COLOR', color: ColorIndex }

View File

@ -19,6 +19,7 @@ import {
receiveOnline,
receiveChatMessage,
receiveChatHistory,
setMobile,
} from './actions';
import store from './ui/store';
@ -56,6 +57,14 @@ function init() {
store.dispatch(urlChange());
});
// check if on mobile
//
function checkMobile() {
store.dispatch(setMobile(true));
document.removeEventListener('touchstart', checkMobile, false);
}
document.addEventListener('touchstart', checkMobile, false);
store.dispatch(initTimer());
store.dispatch(fetchMe());

View File

@ -11,7 +11,13 @@ import { showChatModal } from '../actions';
const ChatButton = ({ open }) => (
<div id="chatbutton" className="actionbuttons" onClick={open}>
<div
id="chatbutton"
className="actionbuttons"
onClick={open}
role="button"
tabIndex={0}
>
<MdForum />
</div>: null
);

View File

@ -0,0 +1,196 @@
/*
*
* @flow
* Menu for WASD keys for mobile users
*/
import React from 'react';
import { getRenderer } from '../ui/renderer';
const btnStyle = {
fontSize: 34,
};
function move(action, bool) {
const renderer = getRenderer();
switch (action) {
case 'FORWARD': {
renderer.controls.moveForward = bool;
break;
}
case 'BACKWARD': {
renderer.controls.moveBackward = bool;
break;
}
case 'LEFT': {
renderer.controls.moveLeft = bool;
break;
}
case 'RIGHT': {
renderer.controls.moveRight = bool;
break;
}
case 'UP': {
renderer.controls.moveUp = bool;
break;
}
case 'DOWN': {
renderer.controls.moveDown = bool;
break;
}
default:
break;
}
}
function cancelMovement() {
const renderer = getRenderer();
renderer.controls.moveForward = false;
renderer.controls.moveBackward = false;
renderer.controls.moveLeft = false;
renderer.controls.moveRight = false;
renderer.controls.moveUp = false;
renderer.controls.moveDown = false;
}
class Mobile3DControls extends React.Component {
constructor() {
super();
}
render() {
return (
<div>
<div
className="actionbuttons"
role="button"
tabIndex={0}
style={{
...btnStyle,
// left: 46,
left: 57,
// bottom: 128,
bottom: 139,
}}
onMouseDown={() => {
move('FORWARD', true);
}}
onMouseUp={() => {
move('FORWARD', false);
}}
onTouchCancel={cancelMovement}
onMouseLeave={cancelMovement}
>
</div>
<div
className="actionbuttons"
role="button"
tabIndex={0}
style={{
...btnStyle,
// left: 46,
left: 57,
bottom: 98,
}}
onMouseDown={() => {
move('BACKWARD', true);
}}
onMouseUp={() => {
move('BACKWARD', false);
}}
onTouchCancel={cancelMovement}
onMouseLeave={cancelMovement}
>
</div>
<div
className="actionbuttons"
role="button"
tabIndex={0}
style={{
...btnStyle,
left: 16,
bottom: 98,
}}
onMouseDown={() => {
move('LEFT', true);
}}
onMouseUp={() => {
move('LEFT', false);
}}
onTouchCancel={cancelMovement}
onMouseLeave={cancelMovement}
>
</div>
<div
className="actionbuttons"
role="button"
tabIndex={0}
style={{
...btnStyle,
// left: 76,
left: 98,
bottom: 98,
}}
onMouseDown={() => {
move('RIGHT', true);
}}
onMouseUp={() => {
move('RIGHT', false);
}}
onTouchCancel={cancelMovement}
onMouseLeave={cancelMovement}
>
</div>
<div
className="actionbuttons"
role="button"
tabIndex={0}
style={{
...btnStyle,
// left: 76,
left: 16,
bottom: 139,
}}
onMouseDown={() => {
move('UP', true);
}}
onMouseUp={() => {
move('UP', false);
}}
onTouchCancel={cancelMovement}
onMouseLeave={cancelMovement}
>
</div>
<div
className="actionbuttons"
role="button"
tabIndex={0}
style={{
...btnStyle,
// left: 76,
left: 98,
bottom: 139,
}}
onMouseDown={() => {
move('DOWN', true);
}}
onMouseUp={() => {
move('DOWN', false);
}}
onTouchCancel={cancelMovement}
onMouseLeave={cancelMovement}
>
</div>
</div>
);
}
}
export default Mobile3DControls;

View File

@ -13,6 +13,7 @@ import GlobeButton from './GlobeButton';
import PalselButton from './PalselButton';
import Palette from './Palette';
import HistorySelect from './HistorySelect';
import Mobile3DControls from './Mobile3DControls';
const UI = ({ isHistoricalView, is3D }) => {
@ -24,6 +25,7 @@ const UI = ({ isHistoricalView, is3D }) => {
<PalselButton />
<Palette />
{(is3D) ? null : <GlobeButton />}
<Mobile3DControls />
<CoolDownBox />
<NotifyBox />
</div>

View File

@ -143,12 +143,12 @@ class VoxelPainterControls extends EventDispatcher {
const spherical = new Spherical();
const sphericalDelta = new Spherical();
let moveLeft = false;
let moveRight = false;
let moveForward = false;
let moveBackward = false;
let moveUp = false;
let moveDown = false;
this.moveLeft = false;
this.moveRight = false;
this.moveForward = false;
this.moveBackward = false;
this.moveUp = false;
this.moveDown = false;
let scale = 1;
const panOffset = new Vector3();
@ -455,30 +455,30 @@ class VoxelPainterControls extends EventDispatcher {
switch (event.keyCode) {
case 38: // up
case 87: // w
moveForward = true;
scope.moveForward = true;
break;
case 37: // left
case 65: // a
moveLeft = true;
scope.moveLeft = true;
break;
case 40: // down
case 83: // s
moveBackward = true;
scope.moveBackward = true;
break;
case 39: // right
case 68: // d
moveRight = true;
scope.moveRight = true;
break;
case 69: // E
moveUp = true;
scope.moveUp = true;
break;
case 67: // C
moveDown = true;
scope.moveDown = true;
break;
default:
break;
@ -497,30 +497,30 @@ class VoxelPainterControls extends EventDispatcher {
switch (event.keyCode) {
case 38: // up
case 87: // w
moveForward = false;
scope.moveForward = false;
break;
case 37: // left
case 65: // a
moveLeft = false;
scope.moveLeft = false;
break;
case 40: // down
case 83: // s
moveBackward = false;
scope.moveBackward = false;
break;
case 39: // right
case 68: // d
moveRight = false;
scope.moveRight = false;
break;
case 69: // E
moveUp = false;
scope.moveUp = false;
break;
case 67: // C
moveDown = false;
scope.moveDown = false;
break;
default:
break;
@ -850,6 +850,15 @@ class VoxelPainterControls extends EventDispatcher {
velocity.set(0, 0, 0);
}
const {
moveRight,
moveLeft,
moveUp,
moveDown,
moveForward,
moveBackward,
} = scope;
direction.x = Number(moveRight) - Number(moveLeft);
direction.y = Number(moveUp) - Number(moveDown);
direction.z = Number(moveForward) - Number(moveBackward);

View File

@ -25,6 +25,9 @@ export type UserState = {
chatMessages: Array,
// minecraft
minecraftname: string,
// just gets set by 3D controls on
// on voxel canvases
isOnMobile: boolean,
};
const initialState: UserState = {
@ -40,6 +43,7 @@ const initialState: UserState = {
totalDailyRanking: {},
chatMessages: [['info', 'Welcome to the PixelPlanet Chat']],
minecraftname: null,
isOnMobile: false,
};
export default function user(
@ -82,6 +86,14 @@ export default function user(
};
}
case 'SET_MOBILE': {
const { mobile: isOnMobile } = action;
return {
...state,
isOnMobile,
};
}
case 'PLACE_PIXEL': {
let { totalPixels, dailyTotalPixels } = state;
totalPixels += 1;

View File

@ -42,6 +42,7 @@ class Renderer {
mouseMoveStart;
raycaster;
pressTime: number;
longTouch: boolean;
pressCdTime: number;
//--
chunkLoader: ChunkLoader = null;
@ -374,10 +375,22 @@ class Renderer {
onDocumentMouseDown() {
this.pressTime = Date.now();
this.longTouch = false;
const state = this.store.getState();
this.mouseMoveStart = state.gui.hover;
}
onDocumentTouchEnd() {
// gets fired before onDocumentMouseUp
// --
// longer press on touch-device -> remove Voxel
const curTime = Date.now();
if (curTime - this.pressTime > 600) {
this.pressCdTime = curTime;
this.longTouch = true;
}
}
onDocumentMouseUp(event) {
const curTime = Date.now();
if (curTime - this.pressCdTime < 200) {
@ -406,6 +419,7 @@ class Renderer {
const {
clientX,
clientY,
button,
} = event;
const {
innerWidth,
@ -430,59 +444,50 @@ class Renderer {
if (intersects.length > 0) {
const intersect = intersects[0];
switch (event.button) {
case 0: {
// left mouse button
const target = intersect.point.clone()
.add(intersect.face.normal.multiplyScalar(0.5))
.floor()
.addScalar(0.5)
.floor();
if (target.clone().sub(camera.position).length() < 120) {
const cell = target.toArray();
store.dispatch(tryPlacePixel(cell));
}
break;
if (button === 0 && !this.longTouch) {
// left mouse button
const target = intersect.point.clone()
.add(intersect.face.normal.multiplyScalar(0.5))
.floor()
.addScalar(0.5)
.floor();
if (target.clone().sub(camera.position).length() < 120) {
const cell = target.toArray();
store.dispatch(tryPlacePixel(cell));
}
case 1: {
// middle mouse button
const target = intersect.point.clone()
.add(intersect.face.normal.multiplyScalar(-0.5))
.floor()
.addScalar(0.5)
.floor();
if (target.y < 0) {
return;
}
if (target.clone().sub(camera.position).length() < 120) {
const cell = target.toArray();
if (this.chunkLoader) {
const clr = this.chunkLoader.getVoxel(...cell);
if (clr) {
store.dispatch(selectColor(clr));
}
} else if (button === 1) {
// middle mouse button
const target = intersect.point.clone()
.add(intersect.face.normal.multiplyScalar(-0.5))
.floor()
.addScalar(0.5)
.floor();
if (target.y < 0) {
return;
}
if (target.clone().sub(camera.position).length() < 120) {
const cell = target.toArray();
if (this.chunkLoader) {
const clr = this.chunkLoader.getVoxel(...cell);
if (clr) {
store.dispatch(selectColor(clr));
}
}
break;
}
case 2: {
// right mouse button
const target = intersect.point.clone()
.add(intersect.face.normal.multiplyScalar(-0.5))
.floor()
.addScalar(0.5)
.floor();
if (target.y < 0) {
return;
}
if (target.clone().sub(camera.position).length() < 120) {
const cell = target.toArray();
store.dispatch(tryPlacePixel(cell, 0));
}
break;
} else if (button === 2 || this.longTouch) {
// right mouse button
const target = intersect.point.clone()
.add(intersect.face.normal.multiplyScalar(-0.5))
.floor()
.addScalar(0.5)
.floor();
if (target.y < 0) {
return;
}
if (target.clone().sub(camera.position).length() < 120) {
const cell = target.toArray();
store.dispatch(tryPlacePixel(cell, 0));
}
default:
break;
}
}
}