The problem what I have is that React TS throws an error for my window.webkitRequestAnimationFrame and window.mozRequestAnimationFrame thinking that I mean 'requestAnimationFrame' instead. Should I replace it with something else?
App.tsx
import React from "react";
export interface Props {
canvas: HTMLElement;
particles: number;
}
function App(props: Props) {
props.canvas = document.getElementById("canvas");
var ctx = props.canvas.getContext("2d");
props.particles = [];
props.canvas.onmousedown = function (e: any) {
for (var i = 0; i < 36 * 2; i++) {
props.particles.push({
x: e.clientX,
y: e.clientY,
angle: i * 5,
size: 5 + Math.random() * 3,
life: 200 + Math.random() * 50,
});
}
};
props.canvas.onmouseup = function () {
//ctx.clearRect(0, 0, 600, 600);
};
var delta = 0;
var last = Date.now();
function animate() {
delta = Date.now() - last;
last = Date.now();
for (var i = 0; i < props.particles.length; i++) {
var p = props.particles[i];
p.x += Math.cos(p.angle) * 4 + Math.random() * 2 - Math.random() * 2;
p.y += Math.sin(p.angle) * 4 + Math.random() * 2 - Math.random() * 2;
p.life -= delta;
p.size -= delta / 50;
if (p.size <= 0) {
p.life = 0;
}
if (p.life <= 0) {
props.particles.splice(i--, 1);
continue;
}
}
}
function render() {
ctx.fillStyle = "#00FF00";
for (var i = 0; i < props.particles.length; i++) {
if (Math.random() < 0.1) {
continue;
}
var p = props.particles[i];
ctx.beginPath();
ctx.arc(p.x, p.y, p.size, 0, Math.PI * 2, false);
ctx.fill();
}
}
window.requestAnimFrame = (function () {
return (
window.requestAnimationFrame ||
window.webkitRequestAnimationFrame ||
window.mozRequestAnimationFrame ||
function (callback) {
window.setTimeout(callback, 1000 / 60);
}
);
})();
(function animloop() {
requestAnimFrame(animloop);
animate();
render();
})();
return <canvas id="canvas" width="100vw" height="100vh"></canvas>;
}
export default App;
Edit:
Edited to only ask one question instead of many in this thread.
requestAnimationFrame() has been available in all major browsers for years by now. According to that link, it looks like the last browser releases that included the prefixed version were release 2012-2014.
So it's probably safe to use requestAnimationFrame directly, and then you can remove the polyfill altogether.
I have this function type() where I define an array texts and I add some values to it and then I set the local texts array to the state array, so it'll be accessible for other functions as well.
var texts = [];
texts.push("Hello", 20, 20)
this.setState({texts: texts})
And this is the state:
state ={
texts:[]
}
I check with the alert() what's the index of 0 of the array to see if it's working, however it says it's undefined:
alert(this.state.texts[0])
This is my whole function:
type()
{
var canvas = document.getElementById('board'),
ctx = canvas.getContext('2d'),
font = '20px sans-serif',
hasInput = false;
var sketch = document.querySelector('#sketch');
var sketch_style = getComputedStyle(sketch);
canvas.width = parseInt(sketch_style.getPropertyValue('width'));
canvas.height = parseInt(sketch_style.getPropertyValue('height'));
var texts = [];
texts.push("Hello", 20, 20)
this.setState({texts: texts})
alert(this.state.texts[0])
ctx.font = font
ctx.fillText("rrwerwewewrewrwerwe", 50, 50)
canvas.onclick = function(e) {
if (hasInput) return;
addInput(e.clientX, e.clientY);
}
//Function to dynamically add an input box:
function addInput(x, y) {
var input = document.createElement('input');
input.type = 'text';
input.style.position = 'fixed';
input.style.left = (x - 4) + 'px';
input.style.top = (y - 4) + 'px';
input.onkeydown = handleEnter;
document.body.appendChild(input);
input.focus();
hasInput = true;
}
//Key handler for input box:
function handleEnter(e) {
var keyCode = e.keyCode;
if (keyCode === 13) {
addText(this.value, parseInt(this.style.left, 10), parseInt(this.style.top, 10));
document.body.removeChild(this);
hasInput = false;
}
}
//Draw the text onto canvas:
function addText(text, x, y) {
ctx.position = 'absolute';
ctx.font = font;
ctx.fillText(text, x, y);
}
}
I believe my react code is trying to access a server directory after its compiled and sent to the client. This means when it looks for the gameLogic.js and style.css files it cant locate them. I'm wondering how I would go about getting the react component im working on to get a copy of them and send them off to the remote client. I get the following errors.
pages/game.js
import * as React from "react";
import Layout from "../components/Layout";
import Separator from "../components/Separator";
import CanvasCanvas from "../components/CanvasCanvas";
export default class extends React.Component {
render() {
return (
<Layout>
<main>
<div className="loginBox5">
<Separator height={50}/>
<div className="center">
<h1>Game Play:</h1>
<Separator height={50}/>
<div id="PlayAreaImg" className="gameContainer">
<CanvasCanvas id={"Memes"}/>
</div>
</div>
<Separator height={350}/>
</div>
</main>
</Layout>
)
}
}
src/gameLogic.js
var keyState = {};
window.addEventListener('keydown',function(e){
keyState[e.keyCode || e.which] = true;
},true);
window.addEventListener('keyup',function(e){
keyState[e.keyCode || e.which] = false;
},true);
x = 100;
function drawObj(ctx, object){
var x = object[0];
var y = object[1];
var wid = object[2];
var hei = object[3];
var r = object[4];
var g = object[5];
var b = object[6];
var t = object[7];
// Renderer usage: Canvas context, x position, y position, object height, object width, red, green, blue, transparency
ctx.fillStyle = "rgba("+String(r)+","+String(g)+","+String(b)+","+String(t)+")"; // colour ball
ctx.fillRect (x, y, wid, hei); // render ball
return ctx;
}
function renderAll(objects){
console.log("### - Render: Starting - ###");
for (var i = 0; i < objects.length; i++) {
// Iterate over numeric indexes from 0 to 5, as everyone expects.
}
console.log("### - Render: Complete - ###");
}
//Define generic move function
function transformR(object, moveAmount, canvasHeight, canvasWidth){
if (keyState[37]){
object[0] -= moveAmount
// console.log("left");
}
if (keyState[38]){
object[1] -= moveAmount
if (object[1] < 0){
// console.log("Top Edge")
object[1] = 0;
}
// console.log("up");
}
if (keyState[39]){
object[0] += moveAmount
// console.log("right");
}
if (keyState[40]){
object[1] += moveAmount
if (object[1] > (canvasHeight-object[3])){
// console.log("Bottom Edge")
object[1] = canvasHeight-object[3];
}
// console.log("down");
}
return object;
}
function transformL(object, moveAmount, canvasHeight, canvasWidth){
if (keyState[65]){
object[0] -= moveAmount
// console.log("left");
}
if (keyState[87]){
object[1] -= moveAmount
if (object[1] < 0){
// console.log("Top Edge")
object[1] = 0;
}
// console.log("up");
}
if (keyState[68]){
object[0] += moveAmount
// console.log("right");
}
if (keyState[83]){
object[1] += moveAmount
if (object[1] > (canvasHeight-object[3])){
// console.log("Bottom Edge")
object[1] = canvasHeight-object[3];
}
// console.log("down");
}
return object;
}
function collisonDetect(ball, paddle){
if (ball[0] < paddle[0] + paddle[2] &&
ball[0] + ball[2] > paddle[0] &&
ball[1] < paddle[1] + paddle[3] &&
ball[3] + ball[1] > paddle[1]) {
ball[8] = -ball[8];
ball[9] = -ball[9];
console.log("inside");
} else {
// console.log("not touching/inside");
}
return ball;
}
function ballMotion(height, width, ball, rightPaddle, leftPaddle){
var x = ball[0];
var y = ball[1];
// collision detection
ball = collisonDetect(ball, leftPaddle);
ball = collisonDetect(ball, rightPaddle);
var xSpeed = ball[8];
var ySpeed = ball[9];
x += xSpeed;
y += ySpeed;
// sides collison detection
if (y <= 0){
y = 0;
ySpeed = -ySpeed;
}
if (y >= height-ball[2]) {
y = height-ball[2];
ySpeed = -ySpeed;
}
if (x <= 0) {
x = 0;
xSpeed = -xSpeed;
leftPoints +=1
}
if (x >= width-ball[3]) {
x = width-ball[3];
xSpeed = -xSpeed;
rightPoints +=1
}
// assign new values
ball[0] = x;
ball[1] = y;
ball[8] = xSpeed;
ball[9] = ySpeed;
return ball;
}
function onPositionUpdate(position){
var lat = position.coords.latitude;
var lng = position.coords.longitude;
console.log("Current position: " + lat + " " + lng);
}
function onDown(event){
cx = event.pageX;
cy = event.pageY;
console.log(cx, cy)
}
// Define objects as follows
// Renderer usage: Canvas context, x position, y position, object height, object width, red, green, blue, transparency
// Cut down usage: X, Y, height, width, red, green, blue, transparency
if (window.innerWidth < window.innerHeight) {
ballDim = [window.innerWidth*.02, window.innerWidth*.02]
} else {
ballDim = [window.innerHeight*.02, window.innerHeight*.02]
}
var ball = [window.innerWidth/2-((window.innerWidth*.02)/2), window.innerHeight*.8*.5-((window.innerHeight*.08)/2), ballDim[0], ballDim[1],200 ,200 ,200 ,3 , 3, 2];
var leftPaddle = [window.innerWidth*.01, window.innerHeight*.8*.5-((window.innerHeight*.08)/2), window.innerWidth*.01, window.innerHeight*.08, 0, 0, 200, 3];
var rightPaddle = [window.innerWidth*.8-(window.innerWidth*.01)-(window.innerWidth*.01), window.innerHeight*.8*.5-((window.innerHeight*.08)/2), window.innerWidth*.01, window.innerHeight*.08, 255, 100, 0, 3];
var leftPoints = 0;
var rightPoints = 0;
// Define gameLoop
function gameLoop(x,y) {
if(navigator.geolocation){
navigator.geolocation.getCurrentPosition(onPositionUpdate);
} else {
console.log("navigator.geolocation is not available");
}
var canvas = document.getElementById("canvas");
var ctx = canvas.getContext("2d");
canvas.addEventListener("mousedown",onDown,false);
var width = window.innerWidth*.8;
var height = window.innerHeight*.8
ctx.canvas.width = width;
ctx.canvas.height = height;
var moveAmount = 3;
var motionTicker = + new Date()
// console.log(motionTicker)
// move checking function
leftPaddle[0] = window.innerWidth*.01;
rightPaddle[0] = window.innerWidth*.8-(window.innerWidth*.01)-(window.innerWidth*.01);
leftPaddle = transformL(leftPaddle, moveAmount, height, width);
rightPaddle = transformR(rightPaddle, moveAmount, height, width);
ball = ballMotion(height, width, ball, rightPaddle, leftPaddle);
ctx.save();
ctx.clearRect(0,0,width,height);
// Render objects in frame
drawObj(ctx, ball);
drawObj(ctx, leftPaddle);
drawObj(ctx, rightPaddle);
ctx.font = String(window.innerWidth*.05)+"px Arial";
ctx.fillStyle = "white";
ctx.fillText(String(rightPoints)+" - "+String(leftPoints), window.innerWidth*.333, window.innerHeight*.1);
ctx.restore();
setTimeout(gameLoop, 1);
await this.forceUpdate();
this.state = {motionTicker}
}
/components/CanvasCanvas.js
import * as React from "react";
export default class extends React.Component {
render() {
return (
<canvas ref={"canvas"} id = {"canvas"} width={640} height={425}/>
)
}
async componentDidMount() {
const script = document.createElement("script");
console.log("ln14")
script.src = "../src/gameLogic.js";
script.async = true;
// console.log(script);
document.head.appendChild(script);
console.log(script);
await this.setState(
{
text: this.props.text,
...this.state
}
);
await this.forceUpdate();
const canvas = this.refs.canvas;
const ctx = canvas.getContext("2d");
ctx.fillText((this.state && this.state.text) ? this.state.text : "Not initialised (nullcheck)", 210, 75);
}
}
Expected result is the gameLogic js file will render its output inside the canvas element and forceUpdate it at the end of each 'frame'.
And the actual result is a string of 404's as follows:
http://localhost:3000/css/style.css net::ERR_ABORTED 404 (Not Found)
index.js:1 Warning: Extra attributes from the server: deluminate_imagetype
GET http://localhost:3000/src/gameLogic.js net::ERR_ABORTED 404 (Not Found)
Thanks for any help you can give in advance.
If you want to access these files after compilation put them inside the static folder for example script.src = "/static/gameLogic.js"
Or use dynamic import
import dynamic from 'next/dynamic'
const gameLogic = dynamic(() => import(`../src/gameLogic.js`))
dynamic-import doc
I am creating a game where i need to move ships at a set speed towards the angle they are facing. I have used this code to move singular ships elsewhere in the game but i assume having them in an array has complicated things.
Any help would be appreciated.
var ship1 = this.addChild(new Ship());
var ship2 = this.addChild(new Ship());
var ship3 = this.addChild(new Ship());
var ship4 = this.addChild(new Ship());
var shipSpeed1 = 10;
var shipArray: Array = [];
shipArray.push(ship1, ship2, ship3, ship4);
for (var i: int = 0; i < shipArray.length; i++) {
var randomX: Number = Math.random() * stage.stageHeight;
var randomY: Number = Math.random() * stage.stageHeight;
shipArray[i].x = randomX;
shipArray[i].y = randomY;
shipArray[i].rotation = 90;
shipArray[i].x += Math.sin(shipArray[i].rotation * (Math.PI / 180)) * shipSpeed1;
shipArray[i].y -= Math.cos(shipArray[i].rotation * (Math.PI / 180)) * shipSpeed1;
}
I've also included this within the same function, but i cant get this to work either. Once again i have had this working
if (shipArray[i].x < 0) { //This allows the boat to leave the scene and
enter on the other side.
shipArray[i].x = 750;
}
if (shipArray[i].x > 750) {
shipArray[i].x = 0;
}
if (shipArray[i].y < 0) {
shipArray[i].y = 600;
}
if (shipArray[i].y > 600) {
shipArray[i].y = 0;
}
First, you need to separate your code into a spawn / initialization phase and an update phase.
Something like the following:
var shipArray: Array = [];
//spawn and set initial values (first phase)
//spawn 4 new ships
var i:int;
for(i=0;i<4;i++){
//instantiate the new ship
var ship:Ship = new Ship();
//add it to the array
shipArray.push(ship);
//set it's initial x/y value
ship.x = Math.random() * (stage.stageWidth - ship.width);
ship.y = Math.random() * (stage.stageHeight - ship.height);
//set it's initial rotation
ship.rotation = Math.round(Math.random() * 360);
//set the ships speed (dynamic property)
ship.speed = 10;
//add the new ship to the display
addChild(ship);
}
//NEXT, add an enter frame listener that runs an update function every frame tick of the application
this.addEventListener(Event.ENTER_FRAME, gameUpdate);
function gameUpdate(e:Event):void {
//loop through each ship in the array
for (var i: int = 0; i < shipArray.length; i++) {
//move it the direction it's rotated, the amount of it's speed property
shipArray[i].x += Math.sin(shipArray[i].rotation * (Math.PI / 180)) * shipArray[i].speed;
shipArray[i].y -= Math.cos(shipArray[i].rotation * (Math.PI / 180)) * shipArray[i].speed;
}
}
hi i need to create an ionic app to draw on image or pdf.
I need to drag the canvas where i want on the image, draw on it, resize it and save in another image wich is the result of the old one plus the draw canvas.
canvas is like this, now i can drag or i can draw, but i'm not capable to set 4 anchor on the edge of canvas to resize it
canvas ion-pinch overflow-scroll="false" id='signatureCanvas' on-drag="true" width="200" height="300" style='border: 1px solid black; background-color: transparent;'
the directive to drag
.directive('ionPinch', function($timeout,$ionicGesture) {
return {
restrict: 'A',
link: function($scope, $element) {
$timeout(function() {
var canvas = $element[0],
posX = 0,
posY = 0,
lastPosX = 0,
lastPosY = 0,
bufferX = 0,
bufferY = 0,
scale = 1,
lastScale,
rotation = 0,
last_rotation, dragReady = 0;
ionic.onGesture('touch drag transform dragend', function(e) {
e.gesture.srcEvent.preventDefault();
e.gesture.preventDefault();
switch (e.type) {
case 'touch':
lastScale = scale;
last_rotation = rotation;
break;
case 'drag':
posX = e.gesture.deltaX + lastPosX;
posY = e.gesture.deltaY + lastPosY;
break;
case 'transform':
rotation = e.gesture.rotation + last_rotation;
scale = e.gesture.scale * lastScale
break;
case 'dragend':
lastPosX = posX;
lastPosY = posY;
lastScale = scale;
break;
}
var transform =
"translate3d(" + posX + "px," + posY + "px, 0) " +
"scale(" + scale + ")" +
"rotate(" + rotation + "deg) ";
e.target.style.transform = transform;
e.target.style.webkitTransform = transform;
}, $element[0]);
});
}
};
})
and the controller to draw
ratio = 1.0;
$scope.dev_width = $window.innerWidth;
$scope.dev_height = $window.innerHeight;
var dev_width = $window.innerWidth;
var dev_height = $window.innerHeight;
console.log(dev_width);
var canvas = document.getElementById('signatureCanvas');
var context = canvas.getContext('2d');
window.addEventListener('resize', resizeCanvas, false);
function resizeCanvas() {
canvas.width = canvas.offsetWidth * ratio;
canvas.height = canvas.offsetHeight * ratio;
canvas.getContext('2d').scale(ratio, ratio);
}
resizeCanvas();
var signaturePad = new SignaturePad(canvas);
$scope.clearCanvas = function() {
signaturePad.clear();
}