Skip to content

Commit

Permalink
added shading for balls
Browse files Browse the repository at this point in the history
  • Loading branch information
Keztur committed Jan 20, 2024
1 parent bf91d27 commit a3b0402
Show file tree
Hide file tree
Showing 3 changed files with 127 additions and 15 deletions.
17 changes: 9 additions & 8 deletions index.html
Original file line number Diff line number Diff line change
Expand Up @@ -30,24 +30,24 @@
padding: 5px;
/* color: red; */
}
.menu div {
.obstacle {
width: 110px;
background-color: silver;
margin: 3px;
padding: 2px;
user-select: none;
}
.menu div:hover {
.obstacle:hover {
color: white;
}
.menu div:active {
.obstacle:active {
background-color: black;
}
.active {
background-color: black !important;
color: white;
}
#debug {
input {
margin: 5px;
}
</style>
Expand All @@ -62,10 +62,11 @@
</div>
<div id="mode" class="hint"></div>
<div id="menu" class="menu">
<div id="rect" onclick="ChangeObstacle(this.id)">Rectangle</div>
<div id="square" onclick="ChangeObstacle(this.id)">Rounded</div>
<div id="force" onclick="ChangeObstacle(this.id)">Force Field</div>
<input type="checkbox" name="debug" id="debug" onclick="updateDebug(this.checked)"><label for="debug">debug</label>
<div id="rect" class="obstacle" onclick="ChangeObstacle(this.id)">Rectangle</div>
<div id="square" class="obstacle" onclick="ChangeObstacle(this.id)">Rounded</div>
<div id="force" class="obstacle" onclick="ChangeObstacle(this.id)">Force Field</div>
<div><input type="checkbox" name="shading" id="shading" onclick="updateShading(this.checked)"><label for="shading">shading</label></div>
<div><input type="checkbox" name="debug" id="debug" onclick="updateDebug(this.checked)"><label for="debug">debug</label></div>
</div>
<script type="module" src="./src/game.js"></script>

Expand Down
9 changes: 6 additions & 3 deletions src/game.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,8 @@ import { runSim, addBall, addForceField, addRectangle, addSquare } from './simul
const canvas = document.getElementById('myCanvas')
export const ctx = canvas.getContext('2d')

let xMouse = 0
let yMouse = 0
export let xMouse = 0
export let yMouse = 0
let xLastMouse = 0
let yLastMouse = 0
let xMouseStartDrag = 0
Expand All @@ -15,7 +15,8 @@ let height = 10

let mode = 2 // 1:bubbles, 2:rigid
let obstacle = ''
let drag = false
export let drag = false
export let mousedown = false

resizeCanvas()

Expand All @@ -38,6 +39,7 @@ function drawObstacle () {
window.ChangeObstacle = ChangeObstacle

canvas.addEventListener('mousedown', (evt) => {
mousedown = true
xMouseStartDrag = xMouse
yMouseStartDrag = yMouse

Expand All @@ -61,6 +63,7 @@ window.addEventListener('mousemove', (evt) => {
}, false)

window.addEventListener('mouseup', (evt) => {
mousedown = false
if (drag) {
drag = false
switch (obstacle) {
Expand Down
116 changes: 112 additions & 4 deletions src/simulation.js
Original file line number Diff line number Diff line change
@@ -1,31 +1,97 @@
import { Ball, ForceField, Rectangle, Square } from './library.js'
import { ctx } from './game.js'
import { ctx, xMouse, yMouse, mousedown, drag } from './game.js'

const balls = []
const ForceFields = []
const rectangles = []
const squares = []
const force = 0.01
let BallCount = 0
let shading = false
let debug = false
let changelight = false
const lightAngle = [-0.4, -0.4]

function updateDebug (flag) {
debug = flag
}
window.updateDebug = updateDebug

function updateShading (flag) {
shading = flag
}
window.updateShading = updateShading

export function runSim (xMouseVec, yMouseVec, width, height, mode) {
BallMove(xMouseVec, yMouseVec)
if (!drag && !changelight) {
BallMove(xMouseVec, yMouseVec)
}
ForceFieldsImpact()
BallBallCollision(mode)
BallWallCollision(width, height)
BallRectangleCollision()
BallSquareCollision()

drawForceFields()
if (shading) {
drawBallShadows()
}
drawBalls()
drawRectangles()
drawSquares()

if (shading) {
drawLightPicker()
}
}

function drawLightPicker () {
const radius = 40
const x = 50
const y = 200
let xOff = radius * lightAngle[0]
let yOff = radius * lightAngle[1]

if (mousedown && !drag) {
const vector = Math.hypot(xMouse - x, yMouse - y)

if (vector < radius) {
changelight = true
}

const xLimit = ((xMouse - x) / vector) * (radius - 10)
const yLimit = ((yMouse - y) / vector) * (radius - 10)

if (changelight) {
xOff = xMouse - x
yOff = yMouse - y

// limits movement range of yellow picker
if ((xOff > 0 && xOff > xLimit) || (xOff < 0 && xOff < xLimit)) {
xOff = xLimit
}
if ((yOff > 0 && yOff > yLimit) || (yOff < 0 && yOff < yLimit)) {
yOff = yLimit
}

lightAngle[0] = xOff / radius
lightAngle[1] = yOff / radius
}
} else {
changelight = false
}

ctx.beginPath()
ctx.arc(x, y, radius, 0, 6.2831)
ctx.fillStyle = 'grey'
ctx.fill()
ctx.closePath()

ctx.beginPath()
ctx.arc(x + xOff, y + yOff, 10, 0, 6.2831)
ctx.fillStyle = 'yellow'
ctx.fill()
ctx.closePath()
}

export function addBall () {
Expand Down Expand Up @@ -386,15 +452,57 @@ function drawBalls () {
drawBall(balls[i].x, balls[i].y, balls[i].radius, balls[i].color)
}
}
function drawBallShadows () {
for (let i = 0; i < BallCount; i++) {
drawBallShadow(balls[i].x, balls[i].y, balls[i].radius)
}
}

function drawBallShadow (x, y, radius) {
const offsetX = radius * -lightAngle[0] * 0.4
const offsetY = radius * -lightAngle[1] * 0.4
ctx.beginPath()
ctx.arc(x + offsetX, y + offsetY, radius, 0, 6.2831)
ctx.fillStyle = 'rgba(0, 0, 0, 0.1)'
ctx.fill()
ctx.closePath()
}

function drawBall (x, y, radius, color) {
ctx.beginPath()
ctx.arc(x, y, radius, 0, 6.2831)
ctx.fillStyle = color

if (shading) {
const offsetX = x + radius * lightAngle[0]
const offsetY = y + radius * lightAngle[1]
const gradient = ctx.createRadialGradient(offsetX, offsetY, 0, offsetX, offsetY, radius * 1.5)
gradient.addColorStop(1, shadeColor(color, -0.3))
gradient.addColorStop(0.2, shadeColor(color, 0.4))
gradient.addColorStop(0, shadeColor(color, 0.5))
ctx.fillStyle = gradient
} else {
ctx.fillStyle = color
}

ctx.fill()
ctx.closePath()
}

function shadeColor (color, factor) {
// convert rgb string to array: "rgb(11,123,1)" -> [11, 123, 1]
const rgb = color.match(/\d+/g).map(Number)

for (let i = 0; i < 3; i++) {
if (factor > 0) {
rgb[i] = Math.floor(rgb[i] + (255 - rgb[i]) * factor)
} else {
rgb[i] = Math.floor(rgb[i] + rgb[i] * factor)
}
}

return `rgb(${rgb[0]}, ${rgb[1]}, ${rgb[2]})`
}

export function drawLine (xFrom, yFrom, xTo, yTo) {
ctx.beginPath() // Start a new path
ctx.moveTo(xFrom, yFrom) // Move the pen to (30, 50)
Expand All @@ -415,7 +523,7 @@ function drawForceField (ff) {
const y = ff.y

const gradient = ctx.createRadialGradient(x, y, 0, x, y, ff.radius)
gradient.addColorStop(0, 'black')
gradient.addColorStop(0, 'lightslategrey')
gradient.addColorStop(1, 'white')

ctx.beginPath()
Expand Down

0 comments on commit a3b0402

Please sign in to comment.