From 4e609c171a5ea84888a2f54a156d5bb7d5775bb0 Mon Sep 17 00:00:00 2001 From: nadiarvi Date: Thu, 1 May 2025 17:17:26 +0900 Subject: [PATCH] add controlPanel component --- lib/_buttons.js | 185 +++++++++++++++++++++++++++++++++ public/assets/down.png | Bin 0 -> 2793 bytes public/assets/empty.png | Bin 0 -> 2351 bytes public/assets/left.png | Bin 0 -> 2842 bytes public/assets/right.png | Bin 0 -> 2855 bytes public/assets/up.png | Bin 0 -> 2810 bytes src/components/Arrow.js | 21 ++++ src/components/ControlPanel.js | 74 +++++++++++++ src/main.js | 10 +- src/scenes/gameScene.js | 39 ++++++- src/scenes/startScene.js | 36 +++---- src/theme.js | 10 -- src/utils/components.js | 40 +++++++ src/utils/theme.js | 32 ++++++ src/world.js | 2 +- 15 files changed, 408 insertions(+), 41 deletions(-) create mode 100644 lib/_buttons.js create mode 100644 public/assets/down.png create mode 100644 public/assets/empty.png create mode 100644 public/assets/left.png create mode 100644 public/assets/right.png create mode 100644 public/assets/up.png create mode 100644 src/components/Arrow.js create mode 100644 src/components/ControlPanel.js delete mode 100644 src/theme.js create mode 100644 src/utils/components.js create mode 100644 src/utils/theme.js diff --git a/lib/_buttons.js b/lib/_buttons.js new file mode 100644 index 0000000..b34d8bb --- /dev/null +++ b/lib/_buttons.js @@ -0,0 +1,185 @@ +const STYLE_DEFAULT = { + background: '#eee', + color: '#111', + border_color: '', + border_width: 0, + border_radius: 5, + + text_font: 'sans-serif', + text_size: 12, +} + +const STYLE_HOVER = { + background: '#ccc', + color: '#111', +} + +const STYLE_PRESSED = { + background: '#aaa', + color: '#000', +} + +const STYLE_DISABLED = { + background: '#777', + color: '#333', +} + +export default class Button { + + #was_pressed = false; + #was_hovering = false; + + #props = { }; + #bounds = { minx: null, miny: null, maxx: null, maxy: null, centerx: null, centery: null }; + #cstyles = { default: STYLE_DEFAULT, hover: STYLE_HOVER, pressed: STYLE_PRESSED, disabled: STYLE_DISABLED }; + + constructor(properties) { + this.#props = Object.assign({ + content: '', + x: null, y: null, + w: null, h: null, + width: null, + height: null, + + style_default: STYLE_DEFAULT, + style_hover: STYLE_HOVER, + style_pressed: STYLE_PRESSED, + style_disabled: STYLE_DISABLED, + + on_mouse_enter: null, + on_mouse_exit: null, + on_press: null, + on_release: null, + + align_x: -1, + align_y: -1, + + enabled: true, + }, properties); + + if ( this.#props.x === null || this.#props.y === null || this.#props.width === null || this.#props.height === null ) + throw( '"x", "y", "width", and "height" must all be defined in the button properties!' ); + + Object.seal(this.#props); + this.#calculateStyles(); + this.#calculateBounds(); + } + + #calculateBounds() { + const offset_x = (this.#props.align_x-1)*this.#props.width/2, + offset_y = (this.#props.align_y-1)*this.#props.height/2; + + this.#bounds.minx = this.#props.x + offset_x, + this.#bounds.miny = this.#props.y + offset_y, + this.#bounds.maxx = this.#props.x + this.#props.width + offset_x, + this.#bounds.maxy = this.#props.y + this.#props.height + offset_y, + this.#bounds.centerx = this.#props.x + this.#props.width/2 + offset_x, + this.#bounds.centery = this.#props.y + this.#props.height/2 + offset_y; + } + + #calculateStyles() { + this.#cstyles.default = Object.assign({}, STYLE_DEFAULT, this.#props.style_default); + this.#cstyles.hover = Object.assign({}, STYLE_DEFAULT, this.#props.style_default, this.#props.style_hover); + this.#cstyles.pressed = Object.assign({}, STYLE_DEFAULT, this.#props.style_default, this.#props.style_pressed); + this.#cstyles.disabled = Object.assign({}, STYLE_DEFAULT, this.#props.style_default, this.#props.style_disabled); + } + + update(properties) { + try { + Object.assign(this.#props, properties); + } catch(e) {console.warn( `Encountered an unrecognized property! Original error: ${e.message}` )} + + if ( 'x' in properties || 'y' in properties || 'width' in properties || 'height' in properties || 'align_x' in properties || 'align_y' in properties ) + this.#calculateBounds(); + + if ( 'style_default' in properties || 'style_hover' in properties || 'style_pressed' in properties || 'style_disabled' in properties ) + this.#calculateStyles(); + } + + /** Shorthand for .update({ x: , y: , ... }) */ + place( x, y, width=null, height=null ) { + this.#props.x = x, + this.#props.y = y; + if ( width !== null ) this.#props.width = width; + if ( height !== null ) this.#props.height = height; + this.#calculateBounds(); + } + + /** Shorthand for .update({ style_: }) */ + style( stylename, style ) { + if (!( 'style_'+stylename in this.#props )) + throw( `Style name must be either "default", "hover", "pressed", or "disabled". Received "${stylename}" instead.` ); + + this.#props['style_'+stylename] = style; + this.#calculateStyles(); + } + + /** Shorthand for .update({ content: }) */ + text( content ) { this.#props.content = content } + + /** Shorthand for .update({ enabled: true }) */ + enable() { this.#props.enabled = true } + + /** Shorthand for .update({ enabled: false }) */ + disable() { this.#props.enabled = false } + + /** + * Returns whether the specified point (by default the mouse's position) is hovering over the button. + * @param {number} x (optional) x override. + * @param {number} y (optional) y override. + * @returns {boolean} + */ + isHovering(x=mouseX, y=mouseY) { + return x > this.#bounds.minx && x < this.#bounds.maxx && y > this.#bounds.miny && y < this.#bounds.maxy; + } + + /** + * Returns whether the button is currently being pressed. + * @returns {boolean} + */ + isPressed() { + return this.isHovering() && mouseIsPressed; + } + + #getCurrentStyle( hovering, pressed ) { + if ( !this.#props.enabled ) return this.#cstyles.disabled; + if ( pressed ) return this.#cstyles.pressed; + if ( hovering ) return this.#cstyles.hover; + return this.#cstyles.default; + } + + /** + * Draws the button on the specified canvas, or the global canvas by default. + * @param context (optional) The p5 canvas to draw to. + */ + draw( context=globalThis ) { + const is_hovering = this.isHovering(); + const is_pressed = mouseIsPressed && (is_hovering || this.#was_pressed); + const style = this.#getCurrentStyle( is_hovering, is_pressed ); + if ( style.background ) context.fill( style.background ); + else context.noFill(); + + + if ( style.border_color && style.border_radius ) { + context.stroke( style.border_color ); + context.strokeWeight( style.border_width ); + } else context.noStroke(); + + context.rect( this.#bounds.minx, this.#bounds.miny, this.#props.width, this.#props.height, style.border_radius ); + + noStroke(); + context.fill( style.color ); + context.textAlign( CENTER, CENTER ); + context.textSize( style.text_size ); + context.textFont( style.text_font ); + context.text( this.#props.content, this.#bounds.centerx, this.#bounds.centery ); + + if ( !this.#was_pressed && is_pressed && this.#props.on_press ) this.#props.on_press(); + if ( this.#was_pressed && !is_pressed && this.#props.on_release ) this.#props.on_release(); + if ( !this.#was_hovering && is_hovering && this.#props.on_mouse_enter ) this.#props.on_mouse_enter(); + if ( this.#was_hovering && !is_hovering && this.#props.on_mouse_exit ) this.#props.on_mouse_exit(); + + this.#was_pressed = is_pressed; + this.#was_hovering = is_hovering; + } +} \ No newline at end of file diff --git a/public/assets/down.png b/public/assets/down.png new file mode 100644 index 0000000000000000000000000000000000000000..69a1fc71afd0963046e45a003c12011bf40e3f4a GIT binary patch literal 2793 zcmeAS@N?(olHy`uVBq!ia0y~yU;;9k7&zE~)R&4Yzkn2Hfk$L90|U1(2s1Lwnj--e zWGoJHcVbv~PUa<$!;&U>cv7h@-A}a#}SDmMeV@L(#+nf7yRlZ9$Jj}0Pc{e4N zvxGhTkflMz!u3qEI~Vlklq-ZMsIyJ&Tz8<0M~JURHHQ6`kc5$-ySKx}1NPdPC%;!V z+>PIM@J+%#@z1)SdFISt_nP5=@y4A|(<}?znHipNFfeckF)#?IFfb^1FfcewU|?ua zU}Ru$1bU%~1?Vcy0ah^W^W{?6d0D%6M%9@!{CQMX{QCFZLL-|_^TF(BP{7HaFWzvb zjPG_C!;es%-7`0wYm9!L!gr^rZkODj(mOG4|K%}MsLeZ^vz3XeA>PNnV|)GI#MwscU`Q^bZlHVCwUVn? z@|pkj$#)hrCzQ@DKV8sqE%n~pcPBL~OHHoF|11A#^MQk@Vfl}$Ydm@dH@a^ap=nT--{#V4`DgR(_sr_PIr(eZJ-yR^(jP31dY1Ej?_Ar+??0ly za4^WdJ^f#IetQ2o`!(w2{w5U%?Q(&c`2Zso1MN67`=e)R>-JX|i*I&+ZS}tV_{jr@ zbEl`;ot4{LXMCNR-HD;V;NQ2*oz)ie&dSZLkI+vOWw5z(_rw2JMK@pnNK=J9|8J?)lB?>+hfWdVpJvq2l7XebMja9#vOQ zm|q{U{jlRL-v6)9KHVhyAZ`uSDzXb78TdEGPTM)dc3154{?lh}XYSnHH$SbvukTq^ zL$xr&2Zq_FQ+HdROY7ff8S8&-=J()DXTGgIox1+IV1RjbVx6%F^Vyw-pA`0Uv| zbN^P_zpk;a-U0~}<~UP!Hx95T?etTfW4-Dh~`_Ikc@&Ba5 zlxIeEDlDh7UeD>!vl&Uw>~fwzAND@WTDxra5my UKZ{)gwoDm3UHx3vIVCg!026^dA^-pY literal 0 HcmV?d00001 diff --git a/public/assets/empty.png b/public/assets/empty.png new file mode 100644 index 0000000000000000000000000000000000000000..a3869b1eabc53d009ed515623d673a69dad7819a GIT binary patch literal 2351 zcmeAS@N?(olHy`uVBq!ia0y~yU;;9k7&zE~)R&4Yzkn2Hfk$L90|U1(2s1Lwnj--e zWGoJHcVbv~PUa<$!;&U>cv7h@-A}a#}#}Q8#$B+ufw>KSgRSZR3FUBusc-d%_ z&~qw*&8y3Ec{$?+uaKqH=Z-P#sR;jOXujcE6(7T$BlmvK=>BcY;Lyjw(4fG`z~BgU zN)rpvbWWg=LJSN7Dhvz?9t;c)69!npi->I7_VT&a@Aoqw=&ycz?fL5pp8StM*A7}2 zgF@}X@jHhtub1&L?0-7vb@iE}ve|2&$K1L1TY_Onr*+P1{XrJUgCU|v-7t7E-Dq5l z#>HT(2q%Jf yECBmK23XJR{r>d(RiJYRU6l@VD!kpXkKss?a_^z(&kqCJHw>PxelF{r5}E*@H7el% literal 0 HcmV?d00001 diff --git a/public/assets/left.png b/public/assets/left.png new file mode 100644 index 0000000000000000000000000000000000000000..57c84041aabb67d6cec8bd28948910b09f47ab21 GIT binary patch literal 2842 zcmeAS@N?(olHy`uVBq!ia0y~yU;;9k7&zE~)R&4Yzkn2Hfk$L90|U1(2s1Lwnj--e zWGoJHcVbv~PUa<$!;&U>cv7h@-A}a#}*LqJE$B+ufw>LNDraTvQc=-Fo#U$rx z2JakXBe+=CGKVUxWSZQ-J)xL6g?*X!4F?mmEnWfaNu1JB0_pSI{df*`mX(Lic=&T) zLZ02h-R%EkpYhzWd2@}i!MO1EtD>30<%SFneGCi@3XBX4jzIS|u>hUG$-uxN#K0h+ z!oZ;5!NA}!VSp86?5w=8_HcXEp4!r%?Til=TfbR5pD)?EMnHcMITC9?Rsf8*=x zuUT>DuF9NzdVcrnzngdt>=b6O$v&;Vd-qM<`12Fr=77yKpU*OUxM)eWgs|Z3f$Cj#oAb>5H_uhR`M&&i>9mJm z-c0ZI|NrT))rWQS^q#%FJNfI&U$=G%R@bx&U})>-|O|G<9>ss%Z?2%Y^06O7#-xqb6(euh7Xfc~UXQJdQ~;c2_&s?zEo zH~ARS-5Ff&)NZtqJNCTT#hl;&d;5wTK+)sWvkp`w+~V1@y!7V%vvoV?Cr3_S{WPi4 zcFvsAXKB~|_A|fF*n7u@Pu-K@!@YO=Y6`Ek762pRT%P@$d1n)U{(tK~|BnHc^YZdX z_dl0a8h$T!d2Kac_E;Ii4^hSgCwKhLs;ri{e@^hOjm_QjI=2}ggwLUBbq35~#@qhY zRNCr4-)%Xm`|rEWrLq6)7}EV1KCHQ0yLFFk&-P-K>-X39pWYkPyZ@wNOxs8V7=paQl(8#KKp|+)GI>=i?&>3U$xL4A-laWK3y&63%ie|IUv1D`wlcG>*= o`wG|?q*93i%EB~i-u-7R(by-m;_$6|z@{vNr>mdKI;Vst0Qmr6qyPW_ literal 0 HcmV?d00001 diff --git a/public/assets/right.png b/public/assets/right.png new file mode 100644 index 0000000000000000000000000000000000000000..1b5d98a035583569e73d72a9f26f445f11372c6f GIT binary patch literal 2855 zcmd5;{ZAWZ9RIdg%1c?<#H54a=%P`hL?%sKd1)OT2AGa2S=?Y*%gkuW;!3xRyo?m; zFq?z~mQ35S((Cq%iJ?}JjkhvdGZE*l#ihaq1u4#=&{Aqgfzm>~#+djA9FZR`&)t(t zzR&mhynS2VEh*fUkeUDhyNZhnN&%?ED;47C#IjQN%LcK;%ZtiT07i23p}>vKy~HL3 zEiDv)(U!JAe9)x%$MONX+Zo|AF#rie#Rd7t>nKZ;$7E+uJa=_2a$bEz(@pDX76~*t zDWAk}AHRCoqclLxH34?;ZQ%!%Dv@BBeTSBGYxBbErOzJNbIV&2^SN7reaB8bgY{#^6PSioBBT6ZOLx|ISKX++_8fVgJ>cE13?E&@1w4M54J0OS*GT>ig*z-NLZ zIpGZafeb}A9TX>PZ8hAwtS%e7q90-G^uufG=@Vr&=#Q$84nbI)A&d;T2Ok_bCE;n2 zzG)t-3@F+mx8C`I3Yw4Z` z&+1X+80l@F5fUL$2~&yirt5l0m^pldmy^v4+WqGma^*k+i}0k>hVj)s!iXkQKTK6N zS5QgQqIQlQZFFXKY|_$D{^+V2mw&on6;jvgPh(ch(2j;4T34->*xeAj=+(D3iBy3k zWcj|Usehs}cxivSM2unbKH=!NCH5eNRF}|FoC6!bd+n{ulJ+-}UOIvIIcDT5#C34) z*gAO%8=bEt4}kM@X!LzEZ5|4F{2#8KRdhPqWxdr`nx6+)e>j*S9(zLIZs$B*UFc6` zwvksi>aqmz;R@YAxyWFeylx6vW!xeH-*g=x8xqNSO>=*Ckjd>jOy#PPC^(^&zowb- zRB(2bPXxy2=Qqwd5%NS7O^cgWxkklm(y`VYAFtgu;&`RboER(pZ>LTqUWo+$VOT$L z^$TCr?`4iHJh|_7Nlg2=@FHm;bUOvM@GM-W3Isg%Q8ZW1jtZ+>Ts=H6oXRaFuTV5E zt2j_tQTAw7A70$DdaR>_fxHtn5MGDFH9lL53?-9i>QjmGFa3buXf$wEbYtj2tnuFoZm8wrPIC^N`vXI^ul(tiq>icpG1o%zTO|cXLB-|20oYn<2LJ#7 literal 0 HcmV?d00001 diff --git a/public/assets/up.png b/public/assets/up.png new file mode 100644 index 0000000000000000000000000000000000000000..251da77a103b90f2768a5bd1d74db9277830c3f2 GIT binary patch literal 2810 zcmeAS@N?(olHy`uVBq!ia0y~yU;;9k7&zE~)R&4Yzkn2Hfk$L90|U1(2s1Lwnj--e zWGoJHcVbv~PUa<$!;&U>cv7h@-A}a#}SHGu=V@L(#+nWb_qpyoLJp8P|bdNQd z>2jmhiHb+A(_S7ZVr`S|urTA%f6J#5E}+k>5*X5C{b7oMXIPoaJ_8Tt$AYY#y^YyM>-F^M{?Fe& zyKK4i@WZN``}avcxG2Ez;fBmM@y&Ac&U)tVx79Oewvlq9T6||%AE@41SGsd{aMk9x zGb?lXc2BN5FR!0B{crhp<~`<24EMJGx2ZIIU1h1h`P|91pOfmW9=1Mwc7J{U>vo_# z^&A39x);hCtfTkusj64t2%@dv$+bUwigj#@|PalbL1Oj7x0(O#gd7j-Q$-d&mUWV5!CM#_7;< zckboFyt=akR{03yUe+5i9m literal 0 HcmV?d00001 diff --git a/src/components/Arrow.js b/src/components/Arrow.js new file mode 100644 index 0000000..089b5d5 --- /dev/null +++ b/src/components/Arrow.js @@ -0,0 +1,21 @@ +export class Arrow { + static images = {}; + + static preload() { + Arrow.images.up = loadImage('/assets/up.png'); + Arrow.images.down = loadImage('/assets/down.png'); + Arrow.images.left = loadImage('/assets/left.png'); + Arrow.images.right = loadImage('/assets/right.png'); + Arrow.images.empty = loadImage('/assets/empty.png'); + } + + constructor(direction) { + this.direction = direction; + this.image = Arrow.images[direction]; + } + + draw(x, y) { + image(this.image, x, y, 40, 40); + } + } + \ No newline at end of file diff --git a/src/components/ControlPanel.js b/src/components/ControlPanel.js new file mode 100644 index 0000000..aec2f4f --- /dev/null +++ b/src/components/ControlPanel.js @@ -0,0 +1,74 @@ +import { Arrow } from "./Arrow"; +import { colors } from "../utils/theme"; + +export class ControlPanel { + constructor({ name, x, y, numBoxes }) { + this.name = name; + this.x = x; + this.y = y; + this.numBoxes = numBoxes; + this.boxWidth = 48; + this.boxHeight = 48; + this.boxSpacing = 8; + this.contents = Array(numBoxes).fill(null); + this.empty = new Arrow('empty'); + this.fontSize = 20; + this.gap = this.fontSize; + } + + updateBox(index, content) { + if (index >= 0 && index < this.numBoxes) { + this.contents[index] = content; + } + } + + draw() { + rectMode(CORNER); + + // Label + fill(colors.tertiary); + noStroke(); + rect(this.x, this.y, this.getPanelWidth(), this.getTextBoxHeight(), 5); + fill(colors.secondary); + textAlign(CENTER, CENTER); + textSize(this.fontSize); + text(this.name, this.x + this.getPanelWidth() / 2, this.y + this.getTextBoxHeight() /2); + + // White panel + fill(255); + noStroke(); + rect(this.x, this.y + 24 + this.gap, this.getPanelWidth(), this.boxHeight + this.boxSpacing, 6); + + // Boxes + for (let i = 0; i < this.numBoxes; i++) { + const bx = this.x + 12 + i * (this.boxWidth + this.boxSpacing); + const by = this.y + 24 + this.gap + (this.boxSpacing * 1) / 2; + + // Draw box + // fill(255); + // stroke(0); + // strokeWeight(1.5); + // rect(bx, by, this.boxWidth, this.boxHeight, 4); + + // Draw content if it exists + if (this.contents[i]) { + if (this.contents[i] instanceof Arrow) { + this.contents[i].draw(bx + this.boxWidth/2 - 20, by + this.boxHeight/2 - 20); + } + } else { + this.empty.draw(bx + this.boxWidth / 2 - 20, by + this.boxHeight / 2 - 20); + } + } + + + + } + + getPanelWidth() { + return this.numBoxes * (this.boxWidth + this.boxSpacing) + 12; + } + + getTextBoxHeight(){ + return this.fontSize + 16; + } +} diff --git a/src/main.js b/src/main.js index 5f4b46d..067481d 100644 --- a/src/main.js +++ b/src/main.js @@ -1,4 +1,5 @@ -import { colors } from './theme.js'; +import { colors } from './utils/theme.js'; +import { Arrow } from './components/Arrow.js'; import StartScene from './scenes/startScene.js'; import GameScene from './scenes/gameScene.js'; @@ -13,7 +14,7 @@ function setup(){ mgr = new SceneManager(); mgr.addScene(StartScene); mgr.addScene(GameScene); - mgr.showScene(StartScene); + mgr.showScene(GameScene); }; function draw(){ @@ -31,8 +32,13 @@ function mousePressed(){ mgr.handleEvent('mousePressed'); }; +function preload(){ + Arrow.preload(); +} + window.setup = setup; window.draw = draw; window.windowResized = windowResized; window.mousePressed = mousePressed; +window.preload = preload; diff --git a/src/scenes/gameScene.js b/src/scenes/gameScene.js index 52ca3a1..a8cfe63 100644 --- a/src/scenes/gameScene.js +++ b/src/scenes/gameScene.js @@ -1,13 +1,39 @@ -import { colors } from '../theme.js'; -import { draw as drawWorld, groundHeight } from '../world.js'; +import { colors } from '../utils/theme.js'; import { Cat } from '../cat.js'; +import { buttonS } from '../utils/theme.js'; +import { MyButton } from '../utils/components.js'; +import { Arrow } from '../components/Arrow.js'; +import { ControlPanel } from '../components/controlPanel.js'; + export default function GameScene() { let cat; + let runButton; + let blocks; + this.name = "GameScene"; this.setup = () => { cat = new Cat(width / 6, height - 167.5, 150); + + runButton = new MyButton({ + x: width / 16 * 15, + y: height / 16, + text: "run >>", + mode: "CENTER", + style: buttonS, + onPress: () => { + console.log("Run button pressed"); + } + }); + + blocks = new ControlPanel({ + name: 'blocks', + x: width / 32, + y: height / 32, + numBoxes: 4 + }); + }; this.draw = () => { @@ -27,12 +53,15 @@ export default function GameScene() { // Sprite cat.draw(); + runButton.draw(); + blocks.draw(); }; this.onResize = () => { - if (cat) { - cat.setPosition(width / 2, height - 177.5); - } + cat.setPosition(width / 2, height - 177.5); + runButton.setPosition((width / 16) * 15, height / 16); + blocks.x = width / 16 - 40; + blocks.y = height / 16 + 8; } } diff --git a/src/scenes/startScene.js b/src/scenes/startScene.js index 926d863..63a6e4d 100644 --- a/src/scenes/startScene.js +++ b/src/scenes/startScene.js @@ -1,6 +1,6 @@ -import { colors } from '../theme.js'; +import { colors } from '../utils/theme.js'; import { Cat } from '../cat.js'; -import { drawRect } from '../utils/draw.js'; +import { buttonL } from '../utils/theme.js'; import GameScene from './gameScene.js'; export default function StartScene() { @@ -13,7 +13,7 @@ export default function StartScene() { }; let startButton; - // this.name = "StartScene"; + this.name = "StartScene"; this.setup = () => { cat = new Cat(width / 2, height - 200, 200); @@ -25,24 +25,24 @@ export default function StartScene() { startButton.locate(width/2, height/2 + 50); // Size - startButton.width = 300; - startButton.height = 75; + startButton.width = buttonL.width; + startButton.height = buttonL.height; // Visual styling - startButton.color = colors.tertiary; - startButton.stroke = colors.secondary; - startButton.strokeWeight = 3; + startButton.color = buttonL.color; + startButton.stroke = buttonL.stroke; + startButton.strokeWeight = buttonL.strokeWeight; // Text properties startButton.text = 'start'; - startButton.textFont = "Pixelify Sans"; - startButton.textSize = 32; - startButton.textColor = colors.secondary; + startButton.textFont = buttonL.textFont; + startButton.textSize = buttonL.textSize; + startButton.textColor = buttonL.textColor; startButton.onPress = () => { console.log("press"); this.sceneManager.showScene(GameScene); - } + }; }; this.draw = () => { @@ -89,19 +89,9 @@ export default function StartScene() { this.onResize = () => { if (cat) { cat.setPosition(width / 2, height - 200); + startButton.locate(width/2, height/2 + 50); } } - - - this.mousePressed = function (){ - const x = mouseX; - const y = mouseY; - - return; - - this.sceneManager.showScene(GameScene); - - }; this.exit = function () { if (cat) { diff --git a/src/theme.js b/src/theme.js deleted file mode 100644 index c51baea..0000000 --- a/src/theme.js +++ /dev/null @@ -1,10 +0,0 @@ -const colors = { - primary: "#a6d1ff", - secondary: "#ff4f64", - tertiary: "#fff29d", - accent: "#a4e4b6" -}; - -export { - colors -} \ No newline at end of file diff --git a/src/utils/components.js b/src/utils/components.js new file mode 100644 index 0000000..0b10163 --- /dev/null +++ b/src/utils/components.js @@ -0,0 +1,40 @@ +export class MyButton { + constructor({ x, y, text, mode = "CORNER", style = {}, onPress = null }) { + this.button = new Clickable(); + + // Apply layout + this.button.mode = mode; + this.button.locate(x, y); + + // Apply text + this.button.text = text; + + // Apply styles + this.button.width = style.width || 150; + this.button.height = style.height || 50; + this.button.color = style.color || "#ffffff"; + this.button.stroke = style.stroke || "#000000"; + this.button.strokeWeight = style.strokeWeight || 2; + this.button.textFont = style.textFont || "sans-serif"; + this.button.textSize = style.textSize || 16; + this.button.textColor = style.textColor || "#000000"; + + // Event + if (onPress) { + this.button.onPress = onPress; + } + } + + draw() { + this.button.draw(); + } + + setText(newText) { + this.button.text = newText; + } + + setPosition(x, y) { + this.button.locate(x, y); + } +}; + \ No newline at end of file diff --git a/src/utils/theme.js b/src/utils/theme.js new file mode 100644 index 0000000..f5cd09d --- /dev/null +++ b/src/utils/theme.js @@ -0,0 +1,32 @@ +const colors = { + primary: "#a6d1ff", + secondary: "#ff4f64", + tertiary: "#fff29d", + accent: "#a4e4b6", +}; + +const button = { + color: colors.tertiary, + stroke: colors.secondary, + strokeWeight: 3, + textFont: "Pixelify Sans", + textColor: colors.secondary +} + +const buttonL = { + ...button, + width: 300, + height: 75, + textSize: 32, +}; + + +const buttonS = { + ...button, + width: 100, + height: 40, + textSize: 20, + strokeWeight: 3, +}; + +export { colors, buttonL, buttonS }; diff --git a/src/world.js b/src/world.js index 94bf5af..de41ca5 100644 --- a/src/world.js +++ b/src/world.js @@ -1,4 +1,4 @@ -import { colors } from './theme.js'; +import { colors } from './utils/theme.js'; export const groundHeight = 100;