Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Invisible objects and objects with text #69

Merged
merged 17 commits into from
Aug 27, 2021
Merged
Show file tree
Hide file tree
Changes from 8 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20,398 changes: 20,341 additions & 57 deletions package-lock.json

Large diffs are not rendered by default.

Binary file added public/wko.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
39 changes: 31 additions & 8 deletions src/components/game/Sketch.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,8 @@ import { GameSound, SoundState, SoundStatus } from './GameSound'
import { buildKeyPressEvent, visualState, flushEvents, canvasResolution, queueEvent } from './SketchUtils'
import { Button } from '@material-ui/core'
import ReplayIcon from '@material-ui/icons/Replay'
import { DrawableMessage, drawMessage } from './messages'
import { DrawableMessage, drawMessage, TEXT_SIZE, TEXT_STYLE } from './messages'
import { CenterFocusStrong } from '@material-ui/icons'

const { round } = Math

Expand Down Expand Up @@ -41,6 +42,17 @@ function wKeyCode(key: string, keyCode: number): string {
return '' //If an unknown key is pressed, a string should be returned
}

function textConfig(sketch: p5, textColor: undefined | string) {
const defaultTextColor = 'blue'
const grey = '#1c1c1c'
sketch.textSize(TEXT_SIZE)
sketch.textStyle(TEXT_STYLE)
sketch.textAlign('center')
sketch.stroke(grey)
const color = textColor && '#' + textColor
sketch.fill(color || defaultTextColor)
}
PalumboN marked this conversation as resolved.
Show resolved Hide resolved

interface SketchProps {
gameProject: GameProject
evaluation: Evaluation
Expand Down Expand Up @@ -119,15 +131,26 @@ function render(interpreter: Interpreter, sketch: p5, images: Map<string, p5.Ima

const messagesToDraw: DrawableMessage[] = []
for (const visual of game.get('visuals')?.innerCollection ?? []) {
const { image: stateImage, position, message } = visualState(interpreter, visual)
const imageObject = image(stateImage)
const x = position.x * cellPixelSize
const y = sketch.height - position.y * cellPixelSize - imageObject.height

sketch.image(imageObject, x, y)
const { image: stateImage, position, message, text, textColor } = visualState(interpreter, visual)
const imageObject = stateImage === undefined ? stateImage : image(stateImage)
PalumboN marked this conversation as resolved.
Show resolved Hide resolved
let x = position.x * cellPixelSize
let y = sketch.height - (position.y + 1) * cellPixelSize
PalumboN marked this conversation as resolved.
Show resolved Hide resolved

if (imageObject) {
x = position.x * cellPixelSize
y = sketch.height - position.y * cellPixelSize - imageObject.height
sketch.image(imageObject, x, y)
}

if (message && visual.get('messageTime')!.innerNumber! > sketch.millis())
messagesToDraw.push({ message, x, y })
messagesToDraw.push({ message, x, y })
PalumboN marked this conversation as resolved.
Show resolved Hide resolved

if (text) {
x = (position.x + 0.5) * cellPixelSize
y = sketch.height - (position.y + 0.5) * cellPixelSize
textConfig(sketch, textColor)
sketch.text(text, x, y)
}
}

messagesToDraw.forEach(drawMessage(sketch))
Expand Down
11 changes: 9 additions & 2 deletions src/components/game/SketchUtils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -32,16 +32,23 @@ export interface VisualState {
image?: string;
position: { x: number; y: number };
message?: string;
text?: string;
textColor?: string;
}

export function visualState(interpreter: Interpreter, visual: RuntimeObject): VisualState {
const image = interpreter.send('image', visual)!.innerString
const imageMethod = visual.module.lookupMethod('image', 0)
const image = imageMethod && interpreter.invoke(imageMethod, visual)!.innerString
PalumboN marked this conversation as resolved.
Show resolved Hide resolved
const position = interpreter.send('position', visual)!
const roundedPosition = interpreter.send('round', position)!
const x = roundedPosition.get('x')!.innerNumber!
const y = roundedPosition.get('y')!.innerNumber!
const message = visual.get('message')?.innerString
return { image, position: { x, y }, message }
const textMethod = visual.module.lookupMethod('text', 0)
const text = textMethod && interpreter.invoke(textMethod, visual)!.innerString
const textColorMethod = visual.module.lookupMethod('textColor', 0)
const textColor = textColorMethod && interpreter.invoke(textColorMethod, visual)!.innerString
return { image, position: { x, y }, message, text, textColor }
}

export function flushEvents(interpreter: Interpreter, ms: number): void {
Expand Down
15 changes: 15 additions & 0 deletions src/components/game/messages.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,17 @@ export interface MessageDrawer {
textWidth(message: string): number;
rect(xPos: number, yPos: number, xSize: number, ySize: number, tl?: number, tr?: number, br?: number, bl?: number): void;
text(message: string, xPos: number, yPos: number, xLimit: number, yLimit: number): void;
fill(color: string): void;
textAlign(alignment: string): void;
textSize(size: number): void;
textStyle(style: string): void;
stroke(color: string): void;
noStroke(): void;
}

export const TEXT_STYLE = 'bold'
export const TEXT_SIZE = 14

const sizeFactor = 50

function messageSizeLimit() {
Expand Down Expand Up @@ -63,12 +72,18 @@ function messageBackgroundPosition(drawer: MessageDrawer, message: DrawableMessa
function drawMessageBackground(drawer: MessageDrawer, message: DrawableMessage) {
const size = messageSize(drawer, message)
const position = messageBackgroundPosition(drawer, message)
drawer.fill('white')
drawer.rect(position.x, position.y, size.x, size.y, 0, 15, 10, 5)
}

export const drawMessage = (drawer: MessageDrawer) => (message: DrawableMessage): void => {
drawMessageBackground(drawer, message)
const position = messageTextPosition(drawer, message)
const limit = messageSizeLimit()
drawer.textSize(TEXT_SIZE)
drawer.textStyle(TEXT_STYLE)
drawer.fill('black')
drawer.textAlign('left')
drawer.noStroke()
drawer.text(message.message, position.x, position.y, limit.x, limit.y)
}
57 changes: 44 additions & 13 deletions src/test/game.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,19 +25,6 @@ const getVisualState = (interpreter: Interpreter, index = 0) => {
}

describe('game', () => {

gameTest('visualStates', 'pepita', ['games/pepita.wpgm'], function (interpreter) {
expect(getVisualState(interpreter)).toStrictEqual({
image: 'pepita.png',
position: { x: 1, y: 1 },
message: undefined,
})
})

gameTest('visualState should round a visuals position', 'visualStateTest', ['games/visualStateTest.wpgm'], function (interpreter) {
expect(getVisualState(interpreter).position).toStrictEqual({ x: 1, y: 2 })
})

gameTest('a visual outside of the canvas should be drawn', 'gameTest', ['games/gameTest.wpgm'], function (interpreter) {
expect(getVisualState(interpreter, 1)).toMatchObject({ image: 'out.png' })
})
Expand Down Expand Up @@ -116,6 +103,12 @@ describe('messages', () => {
textWidth: (text: string) => 5.5 * text.length,
rect: () => { },
text: () => { },
fill: () => { },
textAlign: () => { },
textSize: () => { },
textStyle: () => { },
stroke: () => { },
noStroke: () => { },
}

test('when a message is horizontally out of canvas, it should be inverted', () => {
Expand All @@ -135,6 +128,44 @@ describe('messages', () => {
})
})

describe('VisualState', () => {
gameTest('visualStates', 'pepita', ['games/pepita.wpgm'], function (interpreter) {
expect(getVisualState(interpreter)).toStrictEqual({
image: 'pepita.png',
position: { x: 1, y: 1 },
message: undefined,
text: undefined,
textColor: undefined
})
})

gameTest('complete visual', 'visualStateTest', ['games/visualStateTest.wpgm'], function (interpreter) {
expect(getVisualState(interpreter, 2)).toStrictEqual({
image: 'anImage.png',
position: { x: 0, y: 0 },
message: undefined,
text: 'Sample text',
textColor: 'FF0000FF'
})
})

gameTest('visualState should round a visuals position', 'visualStateTest', ['games/visualStateTest.wpgm'], function (interpreter) {
expect(getVisualState(interpreter).position).toStrictEqual({ x: 1, y: 2 })
})

gameTest('image is optional', 'visualStateTest', ['games/visualStateTest.wpgm'], function (interpreter) {
expect(getVisualState(interpreter, 1).image).toBeUndefined()
})

gameTest('text is optional', 'visualStateTest', ['games/visualStateTest.wpgm'], function (interpreter) {
expect(getVisualState(interpreter, 1).text).toBeUndefined()
})

gameTest('textColor is optional', 'visualStateTest', ['games/visualStateTest.wpgm'], function (interpreter) {
expect(getVisualState(interpreter, 1).textColor).toBeUndefined()
})
PalumboN marked this conversation as resolved.
Show resolved Hide resolved
})

/*
describe('GameSound', () => {

Expand Down
19 changes: 18 additions & 1 deletion src/test/games/visualStateTest.wpgm
Original file line number Diff line number Diff line change
@@ -1,12 +1,29 @@
import wollok.game.*

object myVisual{
object myVisual {
var property position = game.at(1.2, 1.8)

method image() = "noImage.png"
}

object positionableVisual {
var property position = game.at(1.2, 1.8)
}

object completeVisual {

method position() = game.at(0, 0)

method image() = "anImage.png"

method text() = "Sample text"

method textColor() = "FF0000FF"
}

program mockGame {
game.addVisual(myVisual)
game.addVisual(positionableVisual)
game.addVisual(completeVisual)
game.start()
}