From c94ac4e891b2f7ddaf796f0e727a7486c8290dac Mon Sep 17 00:00:00 2001 From: Anahit Martirosyan Date: Tue, 10 Dec 2019 00:37:41 +0400 Subject: [PATCH 1/3] * balls game * add score --- src/assignment3.js | 171 ++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 160 insertions(+), 11 deletions(-) diff --git a/src/assignment3.js b/src/assignment3.js index 45923db..1887ea5 100644 --- a/src/assignment3.js +++ b/src/assignment3.js @@ -1,16 +1,165 @@ -window.onload = function() { - const canvas = document.getElementById('mainDrawingCanvas'); - const resetButton = document.getElementById('resetButton'); - const scoreSpan = document.getElementById('scoreSpan'); +const BALL_COUNT = 100; +const INITIAL_SCORE = 10; +const SCORE_MULTIPLIED = 1.6; +const EXPLOSION_RADIUS = 20; +const EXPLOSION_FADE_TIME = 3000; +const EXPLODING_TIME = 500; +const BALL_SPEED = 10; +const FPS = 60; //frames per second - const context = canvas.getContext('2d'); +window.onload = function () { + const canvas = document.getElementById('mainDrawingCanvas'); + const resetButton = document.getElementById('resetButton'); + resetButton.onclick = () => { + context.clearRect(0, 0, canvas.width, canvas.height); + gameState = false; + }; + const scoreSpan = document.getElementById('scoreSpan'); + const context = canvas.getContext('2d'); + let gameState = false; + let explodedBallsArray = []; + let ballsArray = []; + // draw BALL_COUNT of balls + if (!gameState) { + for (let i = 0; i < BALL_COUNT; i += 1) { + if (!gameState) { + ballsArray[i] = new Ball(); + } + } + } - canvas.addEventListener('click', event => { - const x = event.offsetX; - const y = event.offsetY; - }, false); - resetButton.onclick = () => { + //animate balls + let animateBallsInterval = setInterval(() => { + context.clearRect(0, 0, canvas.width, canvas.height); + ballsArray.forEach(item => { + item.x += item.vx * BALL_SPEED / FPS; + item.y += item.vy * BALL_SPEED / FPS; - } + if (item.x > canvas.width - item.radius || item.x - item.radius < 0) { + item.vx = -item.vx; + } + if (item.y > canvas.height - item.radius || item.y - item.radius < 0) { + item.vy = -item.vy; + } + item.draw(context); + }); + + explodedBallsArray.forEach(explodedBalls => { + explodedBalls.draw(); + }); + if (gameState && explodedBallsArray.length === 0) { + clearInterval(animateBallsInterval); + context.clearRect(0, 0, canvas.width, canvas.height); + gameState = false; + } + + }, 1000 / FPS); + + + canvas.addEventListener('click', event => { + if (!gameState) { + gameState = true; + } else { + return; + } + const x = event.offsetX; + const y = event.offsetY; + startChainReaction(x, y); + }, false); + + function startChainReaction(x, y) { + let firstExplosion = new Ball(); + firstExplosion.x = x; + firstExplosion.y = y; + explodedBallsArray.push(firstExplosion); + explosion(firstExplosion, EXPLODING_TIME); + fadeColor(firstExplosion, EXPLOSION_FADE_TIME); + } + + explodedBallsArray.forEach(explodedBall => { + }); + + + //explosions + setInterval(() => { + explodedBallsArray.forEach(explodedBall => { + const ex = explodedBall.x; + const ey = explodedBall.y; + const eRadius = explodedBall.radius; + ballsArray.forEach(ball => { + const {x, y, radius} = ball; + const distanceSQ = (x - ex) * (x - ex) + (y - ey) * (y - ey); + const radiusSum = radius + eRadius; + if (distanceSQ < radiusSum * radiusSum) { + explosion(ball, EXPLODING_TIME); + fadeColor(ball, EXPLOSION_FADE_TIME); + explodedBallsArray.push(ball); + ballsArray.splice(ballsArray.indexOf(ball), 1); + } + }) + }); + explodedBallsArray = explodedBallsArray.filter(item => item.color.substr(7, 2) !== '00'); + }, 1000 / FPS); + + + //draw a ball + function Ball() { + this.radius = 10; + this.x = Math.random() * (canvas.width - this.radius); + if (this.x < this.radius) { + this.x = this.radius; + } + this.y = Math.random() * (canvas.height - this.radius); + if (this.y < this.radius) { + this.y = this.radius; + } + this.vx = Math.random() * 2 * BALL_SPEED - BALL_SPEED; + // random number between +/- BALL_SPEED + this.vy = Math.sqrt(BALL_SPEED * BALL_SPEED - this.vx * this.vx) * (Math.round(Math.random()) * 2 - 1); + // (square root of ball speed - vx) * (+/- 1) + this.color = '#' + Math.random().toString(16).substr(2, 6) + 'ff'; + this.draw = () => { + context.beginPath(); + context.fillStyle = this.color; + context.arc(this.x, this.y, this.radius, 0, Math.PI * 2); + context.fill(); + }; + } }; + +//state of balls at the explosion moment +function explosion(circle, duration) { + let startTime = new Date().getTime(); + + let explosionInterval = setInterval(() => { + let now = new Date().getTime(); + circle.radius = circle.radius + (EXPLOSION_RADIUS - circle.radius) * (now - startTime) / duration; + if (circle.radius === EXPLOSION_RADIUS) { + clearInterval(explosionInterval); + } + }, 1000 / FPS) +} + +//fade color +function fadeColor(circle, duration) { + let startTime = new Date().getTime(); + let startOpacityVal = parseInt(circle.color.substring(7), 16); + + let fadeInterval = setInterval(() => { + let now = new Date().getTime(); + let value = startOpacityVal - startOpacityVal * (now - startTime) / duration; + let opacity = Math.round(value); + if (opacity < 0) { + opacity = 0; + } + opacity = opacity.toString(16); + if (opacity.length === 1) { + opacity = '0' + opacity; + } + if (opacity.toString() === '00') { + clearInterval(fadeInterval); + } + circle.color = circle.color.substring(0, 7) + opacity; + }, 1000 / FPS); +} \ No newline at end of file From e9541c3b93bb433f183b1fda37f372b30a353235 Mon Sep 17 00:00:00 2001 From: Anahit Martirosyan Date: Mon, 9 Mar 2020 18:11:52 +0400 Subject: [PATCH 2/3] * reset button (to be finished) --- src/JSReactApp/package.json | 5 +- src/JSReactApp/src/App.js | 226 +++++++++++++----------- src/JSReactApp/src/components/Button.js | 4 +- src/JSReactApp/yarn.lock | 113 +++++++++++- src/assignment3.js | 15 +- 5 files changed, 254 insertions(+), 109 deletions(-) diff --git a/src/JSReactApp/package.json b/src/JSReactApp/package.json index 917b069..51c5309 100644 --- a/src/JSReactApp/package.json +++ b/src/JSReactApp/package.json @@ -12,7 +12,10 @@ "dependencies": { "axios": "^0.19.0", "react": "16.9.0", - "react-native": "0.61.5" + "react-native": "0.61.5", + "react-native-gesture-handler": "^1.5.2", + "react-navigation": "^4.0.10", + "react-navigation-stack": "^1.10.3" }, "devDependencies": { "@babel/core": "^7.7.4", diff --git a/src/JSReactApp/src/App.js b/src/JSReactApp/src/App.js index 6233e1d..d1555a4 100644 --- a/src/JSReactApp/src/App.js +++ b/src/JSReactApp/src/App.js @@ -8,124 +8,148 @@ import React, {Component} from 'react'; import { - View, - Text, - FlatList, - StyleSheet, + View, + Text, + FlatList, + StyleSheet, + TouchableOpacity, } from 'react-native'; import Button from './components/Button'; import axios from 'axios'; +import defaults from "@babel/runtime/helpers/esm/defaults"; +import {get} from "react-native/Libraries/TurboModule/TurboModuleRegistry"; const API_BASE_PATH = 'https://jsonplaceholder.typicode.com/'; const POSTS_PATH = `${API_BASE_PATH}posts/`; const USER_PATH = `${API_BASE_PATH}users/`; +const COMMENTS_PATH = `${API_BASE_PATH}comments?postId=`; const postKeyExtractor = (item, index) => { - return `key-${index}`; + return `key-${index}`; }; export default class App extends Component { - constructor(props) { - super(props); - this.state = { - posts: [], - users: {}, - }; - } + constructor(props) { + super(props); + this.state = { + posts: [], + comments: [], + users: {}, + }; + } + + componentDidMount() { + axios.get(POSTS_PATH).then(({data}) => { + + this.setState({posts: data.sort(() => Math.random() - 0.5)}); + + Array.from(data.reduce((acc, item) => { + acc.add(item.userId); + return acc; + }, new Set())).forEach(id => { + axios.get(`${USER_PATH}${id}`).then(({data}) => { + this.setState({users: {...this.state.users, [data.id]: data}}); + }); + }); + }); + } + + render() { + const {posts} = this.state; + const {comments} = this.state; + const {rootContainer, headerButton, headerContainer} = styles; + return + +