This commit is contained in:
ntr 2019-09-09 22:24:33 +10:00
parent 1b8e565455
commit 0f8164c774
12 changed files with 143 additions and 22 deletions

View File

@ -141,12 +141,25 @@ section {
} }
} }
.game { .game-demo {
grid-area: game; grid-area: game;
display: grid;
grid-template-columns: 1fr 2fr;
.game {
display: flex;
flex-flow: column;
.game-construct {
flex: 1;
}
}
} }
.construct-list { .construct-list {
grid-area: vcons; grid-area: vcons;
height: 100%;
svg { svg {
height: 100%; height: 100%;

View File

@ -8,6 +8,8 @@ export const setAnimSource = value => ({ type: 'SET_ANIM_SOURCE', value });
export const setAnimTarget = value => ({ type: 'SET_ANIM_TARGET', value }); export const setAnimTarget = value => ({ type: 'SET_ANIM_TARGET', value });
export const setAnimText = value => ({ type: 'SET_ANIM_TEXT', value }); export const setAnimText = value => ({ type: 'SET_ANIM_TEXT', value });
export const setDemo = value => ({ type: 'SET_DEMO', value });
export const setActiveItem = value => ({ type: 'SET_ACTIVE_VAR', value }); export const setActiveItem = value => ({ type: 'SET_ACTIVE_VAR', value });
export const setActiveSkill = (constructId, skill) => ({ type: 'SET_ACTIVE_SKILL', value: constructId ? { constructId, skill } : null }); export const setActiveSkill = (constructId, skill) => ({ type: 'SET_ACTIVE_SKILL', value: constructId ? { constructId, skill } : null });
export const setCombiner = value => ({ type: 'SET_COMBINER', value: Array.from(value) }); export const setCombiner = value => ({ type: 'SET_COMBINER', value: Array.from(value) });

View File

@ -68,6 +68,7 @@ class ConstructAnimation extends Component {
const animSkill = removeTier(skill); const animSkill = removeTier(skill);
if (!constructId.includes(construct.id)) return false; if (!constructId.includes(construct.id)) return false;
// find target animation // find target animation
const chooseAnim = (animSkill) => { const chooseAnim = (animSkill) => {
switch (animSkill) { switch (animSkill) {

View File

@ -1,8 +1,51 @@
const { connect } = require('preact-redux');
const preact = require('preact'); const preact = require('preact');
const sample = require('lodash/sample');
const actions = require('../actions');
const shapes = require('./shapes'); const shapes = require('./shapes');
const molecule = require('./molecule');
const { TIMES: { SOURCE_AND_TARGET_TOTAL_DURATION } } = require('./../constants');
const { ConstructAvatar } = require('./construct');
const { ConstructAnimation } = require('./animations');
const addState = connect(
function receiveState(state) {
const {
account,
itemInfo,
demo,
} = state;
return {
account,
itemInfo,
demo,
};
},
function receiveDispatch(dispatch) {
function setAnimTarget(anim) {
dispatch(actions.setAnimTarget(anim));
}
return { setAnimTarget };
}
);
function Demo(args) { function Demo(args) {
const {
demo,
itemInfo,
account,
setAnimTarget,
} = args;
if (!demo || !itemInfo.items.length || account) return false;
const vboxDemo = () => { const vboxDemo = () => {
const phase = this.state.phase || 'vbox'; const phase = this.state.phase || 'vbox';
const items = this.state.items || ['Red', 'Red', 'Attack']; const items = this.state.items || ['Red', 'Red', 'Attack'];
@ -13,8 +56,6 @@ function Demo(args) {
equipped, equipped,
} = this.state; } = this.state;
console.log(combiner, this.state);
function inventoryBtn(i, j) { function inventoryBtn(i, j) {
if (!i) return <button disabled class='empty' >&nbsp;</button>; if (!i) return <button disabled class='empty' >&nbsp;</button>;
const highlighted = combiner.indexOf(j) > -1; const highlighted = combiner.indexOf(j) > -1;
@ -79,22 +120,22 @@ function Demo(args) {
return this.setState({ combiner: [], items: ['Red', 'Red', 'Attack'], equipped: false, equipping: false }); return this.setState({ combiner: [], items: ['Red', 'Red', 'Attack'], equipped: false, equipping: false });
} }
if (items.length === 1 && combiner[0] === 0) { if (items[0] === 'Strike' && combiner[0] === 0) {
return this.setState({ combiner: [], items: [''], equipped: true, equipping: false }); return this.setState({ combiner: [], items: ['', '', ''], equipped: true, equipping: false });
} }
if (items.length === 1) { if (items[0] === 'Strike') {
return this.setState({ combiner: [0], items: ['Strike'], equipping: true }); return this.setState({ combiner: [0], items: ['Strike', '', ''], equipping: true });
} }
if (combiner.length === 3) { if (combiner.length === 3) {
return this.setState({ combiner: [], items: ['Strike'] }); return this.setState({ combiner: [], items: ['Strike', '', ''] });
} }
combiner.push(combiner.length); combiner.push(combiner.length);
this.setState({ combiner }); this.setState({ combiner });
return true; return true;
}, 1500); }, 2000);
const skills = ['Strike']; const skills = ['Strike'];
@ -106,10 +147,10 @@ function Demo(args) {
<div class="news"> <div class="news">
{inventoryElement()} {inventoryElement()}
<div class='construct-list'> <div class='construct-list'>
{[0, 1, 2].map(i => ( {demo[0].constructs.map((c, i) => (
<div class="instance-construct" key={i}> <div class="instance-construct" key={i}>
{molecule()} <h2 class="name" >{c.name}</h2>
<h2 class="name" ></h2> <ConstructAvatar construct={c} />
<div class="skills"> <div class="skills">
{i === 0 && this.state.equipped {i === 0 && this.state.equipped
? <button>Strike</button> ? <button>Strike</button>
@ -129,15 +170,42 @@ function Demo(args) {
); );
}; };
setTimeout(() => {
setAnimTarget({
skill: sample(itemInfo.items.filter(i => i.skill)).item,
constructId: [sample(demo[1].constructs).id],
player: Math.round(Math.random()),
direction: 0,
});
// setTimeout(setAnimTarget(null), 5000);
}, 2000);
const gameDemo = () => {
return (
<div class="game-demo">
<h2>GAME PHASE</h2>
<div class="game">
<div class="game-construct">
<ConstructAvatar construct={demo[1].constructs[0]} />
<ConstructAnimation construct={demo[1].constructs[0]} />
</div>
<div></div>
<div class="game-construct">
<ConstructAvatar construct={demo[1].constructs[1]} />
<ConstructAnimation construct={demo[1].constructs[1]} />
</div>
</div>
</div>
);
};
return ( return (
<section class='demo'> <section class='demo'>
{vboxDemo()} {vboxDemo()}
<div class="game"> {gameDemo()}
<h2>GAME PHASE</h2>
</div>
</section> </section>
); );
} }
module.exports = Demo; module.exports = addState(Demo);

View File

@ -42,7 +42,6 @@ const addState = connect(
function receiveDispatch(dispatch) { function receiveDispatch(dispatch) {
function setActiveSkill(constructId, skill) { function setActiveSkill(constructId, skill) {
dispatch(actions.setActiveSkill(constructId, skill)); dispatch(actions.setActiveSkill(constructId, skill));
// particlesJS(`particles-${constructId}`, config);
} }
function setActiveConstruct(construct) { function setActiveConstruct(construct) {

View File

@ -54,9 +54,9 @@ function Welcome() {
<div class="news"> <div class="news">
<h1>mnml.gg</h1> <h1>mnml.gg</h1>
<p>mnml is a turn-based 1v1 strategy game in an abstract setting.</p> <p>mnml is a turn-based 1v1 strategy game in an abstract setting.</p>
<p>build your team of 3 constructs from a shifting meta of skills, effects and specialisations in order to outplay your opponents.</p> <p>outplay your opponents by building your team of 3 constructs from a shifting meta of skills, effects and specialisations.</p>
<p>simple rules, complex interactions, simultaneous turns to increase the pace, and a unique speed mechanic;</p> <p>simple rules, complex interactions, simultaneous turns to increase the pace, and a unique speed mechanic;</p>
<p>mnml is a tactical game in a genre of its own.</p> <p>mnml is a tactical game unlike any other.</p>
<p>free to play</p> <p>free to play</p>
<p>no email required</p> <p>no email required</p>
<p>glhf</p> <p>glhf</p>

View File

@ -18,6 +18,10 @@ function registerEvents(store) {
store.dispatch(actions.setPing(ping)); store.dispatch(actions.setPing(ping));
} }
function setDemo(d) {
store.dispatch(actions.setDemo(d));
}
function setNav(v) { function setNav(v) {
store.dispatch(actions.setNav(v)); store.dispatch(actions.setNav(v));
} }
@ -229,6 +233,7 @@ function registerEvents(store) {
setAccountInstances, setAccountInstances,
setActiveItem, setActiveItem,
setActiveSkill, setActiveSkill,
setDemo,
setConstructList, setConstructList,
setNewConstruct, setNewConstruct,
setGame, setGame,

View File

@ -23,6 +23,8 @@ module.exports = {
animTarget: createReducer(null, 'SET_ANIM_TARGET'), animTarget: createReducer(null, 'SET_ANIM_TARGET'),
animText: createReducer(null, 'SET_ANIM_TEXT'), animText: createReducer(null, 'SET_ANIM_TEXT'),
demo: createReducer(null, 'SET_DEMO'),
combiner: createReducer([], 'SET_COMBINER'), combiner: createReducer([], 'SET_COMBINER'),
constructs: createReducer([], 'SET_CONSTRUCTS'), constructs: createReducer([], 'SET_CONSTRUCTS'),
constructEditId: createReducer(null, 'SET_CONSTRUCT_EDIT_ID'), constructEditId: createReducer(null, 'SET_CONSTRUCT_EDIT_ID'),

View File

@ -202,10 +202,14 @@ function createSocket(events) {
events.setItemInfo(info); events.setItemInfo(info);
} }
function onDemo(v) {
events.setDemo(v);
}
let pongTimeout; let pongTimeout;
function onPong() { function onPong() {
events.setPing(Date.now() - ping); events.setPing(Date.now() - ping);
// pongTimeout = setTimeout(sendPing, 1000); pongTimeout = setTimeout(sendPing, 10000);
} }
// ------------- // -------------
@ -227,6 +231,7 @@ function createSocket(events) {
InstanceState: onInstanceState, InstanceState: onInstanceState,
ItemInfo: onItemInfo, ItemInfo: onItemInfo,
Pong: onPong, Pong: onPong,
Demo: onDemo,
QueueRequested: () => events.notify('pvp queue request received'), QueueRequested: () => events.notify('pvp queue request received'),
QueueJoined: () => events.notify('you have joined the pvp queue'), QueueJoined: () => events.notify('you have joined the pvp queue'),

View File

@ -763,6 +763,25 @@ pub fn instance_game_finished(tx: &mut Transaction, game: &Game, instance_id: Uu
Ok(()) Ok(())
} }
pub fn demo() -> Result<Vec<Player>, Error> {
let bot = bot_player();
// generate bot imgs for the client to see
for c in bot.constructs.iter() {
img::molecular_write(c.img)?;
};
let bot2 = bot_player();
// generate bot imgs for the client to see
for c in bot2.constructs.iter() {
img::molecular_write(c.img)?;
};
Ok(vec![bot, bot2])
}
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {
use super::*; use super::*;

View File

@ -27,3 +27,4 @@ pub fn bot_player() -> Player {
let constructs = instance_mobs(bot_id); let constructs = instance_mobs(bot_id);
Player::new(bot_id, &name(), constructs).set_bot(true) Player::new(bot_id, &name(), constructs).set_bot(true)
} }

View File

@ -21,10 +21,12 @@ use account;
use construct::{Construct}; use construct::{Construct};
use events::{Event}; use events::{Event};
use game::{Game, game_state, game_skill, game_skill_clear, game_ready}; use game::{Game, game_state, game_skill, game_skill_clear, game_ready};
use instance::{Instance, instance_state, instance_practice, instance_ready}; use instance::{Instance, instance_state, instance_practice, instance_ready, demo};
use item::{Item, ItemInfoCtr, item_info}; use item::{Item, ItemInfoCtr, item_info};
use mtx; use mtx;
use mail; use mail;
use player::{Player};
use payments; use payments;
use mail::Email; use mail::Email;
use pg::{Db}; use pg::{Db};
@ -41,6 +43,8 @@ pub enum RpcMessage {
AccountInstances(Vec<Instance>), AccountInstances(Vec<Instance>),
AccountShop(mtx::Shop), AccountShop(mtx::Shop),
Demo(Vec<Player>),
ConstructSpawn(Construct), ConstructSpawn(Construct),
GameState(Game), GameState(Game),
ItemInfo(ItemInfoCtr), ItemInfo(ItemInfoCtr),
@ -268,6 +272,8 @@ impl Handler for Connection {
// tx should do nothing // tx should do nothing
tx.commit().unwrap(); tx.commit().unwrap();
} else {
self.ws.send(RpcMessage::Demo(demo().unwrap())).unwrap();
} }
Ok(()) Ok(())