diff --git a/package.json b/package.json index f9fc341..28e808b 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "vcs-game-maker", - "version": "0.22.0", + "version": "0.23.0", "private": true, "scripts": { "serve": "vue-cli-service serve", diff --git a/src/blocks/event.js b/src/blocks/event.js index 96add74..d1ff09d 100644 --- a/src/blocks/event.js +++ b/src/blocks/event.js @@ -1,12 +1,23 @@ import * as Blockly from 'blockly/core'; -import {START_ICON, SYSTEM_ICON} from './icon'; +import {GAMEOVER_ICON, GAME_ICON, START_ICON, SYSTEM_ICON, TITLE_ICON, UPDATE_ICON} from './icon'; const EVENT_OPTIONS = [ [`${SYSTEM_ICON} ${START_ICON} System start`, `system_start`], + [`${TITLE_ICON} ${START_ICON} Title screen start`, `title_start`], + [`${TITLE_ICON} ${UPDATE_ICON} Title screen update`, `title_update`], + [`${GAME_ICON} ${START_ICON} Gameplay start`, `gameplay_start`], + [`${GAMEOVER_ICON} ${START_ICON} Gameover start`, `gameover_start`], + [`${GAMEOVER_ICON} ${UPDATE_ICON} Gameover update`, `gameover_update`], +]; + +const STATE_OPTIONS = [ + [`${TITLE_ICON} Title screen`, 'title'], + [`${GAME_ICON} Gameplay`, 'gameplay'], + [`${GAMEOVER_ICON} Gameover`, 'gameover'], ]; Blockly.defineBlocksWithJsonArray([ - // Block for startup code + // Block for events { 'type': 'event_block', 'message0': 'On %1', @@ -25,6 +36,22 @@ Blockly.defineBlocksWithJsonArray([ 'previousStatement': null, 'nextStatement': null, 'colour': 'rgb(39, 176, 176)', - 'tooltip': 'Will be executed exactly one time when the ROM boots up', + 'tooltip': 'Will be executed when a given event happens', + }, + // Block for changing game state + { + 'type': 'event_change_state', + 'message0': 'Change state to %1', + 'args0': [ + { + 'type': 'field_dropdown', + 'name': 'STATE', + 'options': STATE_OPTIONS, + }, + ], + 'previousStatement': null, + 'nextStatement': null, + 'colour': 'rgb(39, 176, 176)', + 'tooltip': 'Change game state to a given one', }, ]); diff --git a/src/blocks/icon.js b/src/blocks/icon.js index 2ddad93..bd49c8c 100644 --- a/src/blocks/icon.js +++ b/src/blocks/icon.js @@ -13,3 +13,7 @@ export const SOUND_ICON = String.fromCodePoint(0x1F509); export const ANIMATION_ICON = String.fromCodePoint(0x1F3AC); export const SYSTEM_ICON = String.fromCodePoint(0x1F3AB); export const START_ICON = String.fromCodePoint(0x25B6) + String.fromCodePoint(0xFE0F); +export const TITLE_ICON = String.fromCodePoint(0x1F4FA); +export const UPDATE_ICON = String.fromCodePoint(0x1F3C3); +export const GAME_ICON = String.fromCodePoint(0x1F47E); +export const GAMEOVER_ICON = String.fromCodePoint(0x2620) + String.fromCodePoint(0xFE0F); diff --git a/src/components/blockly-toolbox.xml.hbs b/src/components/blockly-toolbox.xml.hbs index 978201d..88fbf82 100644 --- a/src/components/blockly-toolbox.xml.hbs +++ b/src/components/blockly-toolbox.xml.hbs @@ -181,7 +181,29 @@ + + + gameover + + + + title_update + + + + + joy0fire + + + + + gameplay + + + + + diff --git a/src/generators/bbasic.bb.hbs b/src/generators/bbasic.bb.hbs index 3afa4ad..a04f88a 100644 --- a/src/generators/bbasic.bb.hbs +++ b/src/generators/bbasic.bb.hbs @@ -64,33 +64,22 @@ end {{{ systemStartEvent }}} +fullgameloop + +{{{ titleStartEvent }}} + +{{{ titleUpdateEvent }}} + +{{{ gamePlayStartEvent }}} + rem ************************************************************************** rem Main loop: - rem - set colors and record last coordinates of player sprites rem ************************************************************************** main - rem ************************************************************************** - rem Draw loop: - rem - Draws the screen and handles user input. Moves the sprites and - rem - the ball's position and handles collisions - rem ************************************************************************** -draw - COLUP1 = player1realcolor - COLUP0 = player0realcolor - NUSIZ0 = player0size - NUSIZ1 = player1size + gosub commongamelogic drawscreen - rem ************************************************************************** - rem Backgrounds generated by vcs-game-maker. - rem ************************************************************************** - - if newbackground = 0 then goto backgroundchangeend -{{{ generatedBackgrounds }}} -backgroundchangeend - newbackground = 0 - rem ************************************************************************** rem Code generated by vcs-game-maker. rem ************************************************************************** @@ -100,7 +89,20 @@ backgroundchangeend rem ************************************************************************** rem End of generated code. rem ************************************************************************** + + goto main +{{{ gameOverStartEvent }}} + +{{{ gameOverUpdateEvent }}} + + goto fullgameloop + + rem ************************************************************************** + rem Common game logic subroutine. + rem ************************************************************************** + +commongamelogic rem ************************************************************************** rem Sound handling. rem ************************************************************************** @@ -111,7 +113,29 @@ backgroundchangeend if channnel1duration = 1 then AUDV1 = 0 if channnel1duration <> 0 then channnel1duration = channnel1duration - 1 - goto main - - rem if 0 then a = a - \ No newline at end of file + + rem ************************************************************************** + rem - Draws the screen and handles user input. Moves the sprites and + rem - the ball's position and handles collisions + rem ************************************************************************** + COLUP1 = player1realcolor + COLUP0 = player0realcolor + NUSIZ0 = player0size + NUSIZ1 = player1size + + rem ************************************************************************** + rem Backgrounds generated by vcs-game-maker. + rem ************************************************************************** + + if newbackground = 0 then goto backgroundchangeend +{{{ generatedBackgrounds }}} +backgroundchangeend + newbackground = 0 + + rem ************************************************************************** + rem Animations generated by vcs-game-maker. + rem ************************************************************************** + + {{{ generatedAnimations }}} + + return diff --git a/src/generators/bbasic.js b/src/generators/bbasic.js index 4a38fee..5276447 100644 --- a/src/generators/bbasic.js +++ b/src/generators/bbasic.js @@ -192,14 +192,22 @@ Blockly.BBasic.finish = function(code) { code = Blockly.BBasic.normalizeIndents(code); const generatedBackgrounds = Blockly.BBasic.generateBackgrounds(); - const animation = Blockly.BBasic.generateAnimations(); + const generatedAnimations = Blockly.BBasic.generateAnimations(); + const systemStartEvent = this.generateGameEvent('system_start'); + const titleStartEvent = this.generateGameEvent('title_start'); + const titleUpdateEvent = this.generateGameLoopEvent('title_update'); + const gamePlayStartEvent = this.generateGameEvent('gameplay_start'); + const gameOverStartEvent = this.generateGameEvent('gameover_start'); + const gameOverUpdateEvent = this.generateGameEvent('gameover_update'); this.isInitialized = false; this.nameDB_.reset(); - const generatedBody = definitions.join('\n\n') + '\n\n\n' + animation + '\n\n\n' + code; - return handlebarsTemplate({generatedBody, generatedBackgrounds, systemStartEvent}); + const generatedBody = definitions.join('\n\n') + '\n\n\n' + code; + return handlebarsTemplate({generatedBody, generatedBackgrounds, generatedAnimations, + systemStartEvent, titleStartEvent, titleUpdateEvent, gamePlayStartEvent, + gameOverStartEvent, gameOverUpdateEvent}); }; Blockly.BBasic.normalizeIndents = function(code) { @@ -365,16 +373,32 @@ Blockly.BBasic.addGameEvent = function(eventName, code) { this.getGameEvent(eventName).push(code); }; -Blockly.BBasic.generateGameEvent = function(eventName) { - const eventCode = this.getGameEvent(eventName).join('\n\n'); +Blockly.BBasic.generateGameEvent = function(eventName, + codeGenerator = (eventName, eventCode) => eventCode.join('\n\n')) { + const eventCode = codeGenerator(eventName, this.getGameEvent(eventName)); return this.normalizeIndents([ 'rem **************************************************************************', `rem Event: ${eventName}.`, 'rem **************************************************************************', + `@${eventName}_begin`, eventCode, + `@${eventName}_end`, ].join('\n')); }; +Blockly.BBasic.generateGameLoopEvent = function(eventName) { + return this.generateGameEvent(eventName, (eventName, eventCode) => { + const innerCode = eventCode.join('\n\n'); + if (!innerCode.trim()) return ''; + return [ + 'gosub commongamelogic', + 'drawscreen', + innerCode, + `goto ${eventName}_begin`, + ].join('\n'); + }); +}; + Blockly.BBasic.generateBackgrounds = function() { const backgroundsStorage = useBackgroundsStorage(); diff --git a/src/generators/bbasic/event.js b/src/generators/bbasic/event.js index 5f74583..29f7448 100644 --- a/src/generators/bbasic/event.js +++ b/src/generators/bbasic/event.js @@ -8,4 +8,11 @@ export default (Blockly) => { Blockly.BBasic.addGameEvent(eventName, code); return ''; }; + + Blockly.BBasic['event_change_state'] = function(block) { + // Change game state + const stateName = Blockly.BBasic.nameDB_.getName(block.getFieldValue('STATE'), + Blockly.VARIABLE_CATEGORY_NAME); + return `goto ${stateName}_start_begin`; + }; };