mirror of
https://github.com/thilo-behnke/wasm-pong.git
synced 2026-07-10 18:20:00 +00:00
working score through network
This commit is contained in:
@@ -68,7 +68,7 @@
|
||||
<Canvas debug={debug} session={session} inputs={inputs} tick={tick} handleError={handleError} let:dimensions={dimensions}>
|
||||
<Fps></Fps>
|
||||
<Line x={dimensions.width / 2} y={0} height={dimensions.height} dashed={true}></Line>
|
||||
<Score dimensions={dimensions} score={tick.score}></Score>
|
||||
<Score dimensions={dimensions} score={tick?.state?.score}></Score>
|
||||
</Canvas>
|
||||
</div>
|
||||
<div class="game-area__hud">
|
||||
|
||||
@@ -1,15 +1,19 @@
|
||||
<script lang="ts">
|
||||
import {gameField} from "../store/engine";
|
||||
import {networkTickEvents, sessionInputs} from "../store/session";
|
||||
import {gameStateEvents, networkTickEvents, sessionInputs} from "../store/session";
|
||||
import type {GameState} from "../store/model/session";
|
||||
|
||||
export let killLoopOnError = true;
|
||||
|
||||
let frame: number;
|
||||
|
||||
let state: GameState;
|
||||
$: state = $gameStateEvents;
|
||||
|
||||
$: if (networkTickEvents && $networkTickEvents.hasNext) {
|
||||
const tick = networkTickEvents.next();
|
||||
if (tick != null) {
|
||||
gameField.update(tick.objects);
|
||||
gameField.update(tick.objects, state);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -2,12 +2,13 @@
|
||||
import {sessionInputs} from "../store/session";
|
||||
import type {LocalSession} from "../store/model/session";
|
||||
import TickWrapper from "./TickWrapper.svelte";
|
||||
import {gameField} from "../store/engine";
|
||||
|
||||
export let session: LocalSession;
|
||||
</script>
|
||||
|
||||
{#if session && sessionInputs}
|
||||
<TickWrapper inputs={$sessionInputs} let:tick={tick} let:inputs={inputs} let:handleError={handleError}>
|
||||
<TickWrapper gameFieldStore={gameField} inputs={$sessionInputs} let:tick={tick} let:inputs={inputs} let:handleError={handleError}>
|
||||
<slot inputs={inputs} tick={tick} handleError={handleError} events={[]}></slot>
|
||||
</TickWrapper>
|
||||
{/if}
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
<script lang="ts">
|
||||
|
||||
import type {GameScore} from "../store/engine";
|
||||
import Text from "./Text.svelte";
|
||||
import type {GameScore} from "../store/model/session";
|
||||
|
||||
export let dimensions: { width: number, height: number };
|
||||
export let score: GameScore;
|
||||
@@ -9,7 +8,7 @@
|
||||
|
||||
{#if score}
|
||||
<Text
|
||||
text={score.player1.toString()}
|
||||
text={score.player_1.toString()}
|
||||
fontSize=40
|
||||
fontFamily='Courier New'
|
||||
align='left'
|
||||
@@ -18,7 +17,7 @@
|
||||
y={20}/>
|
||||
|
||||
<Text
|
||||
text={score.player2.toString()}
|
||||
text={score.player_2.toString()}
|
||||
fontSize=40
|
||||
fontFamily='Courier New'
|
||||
align='left'
|
||||
|
||||
@@ -39,4 +39,4 @@
|
||||
}
|
||||
</script>
|
||||
|
||||
<slot tick={gameFieldStore} inputs={inputs} handleError={handleError}></slot>
|
||||
<slot tick={$gameFieldStore} inputs={inputs} handleError={handleError}></slot>
|
||||
|
||||
@@ -68,7 +68,7 @@ export type GameFieldState = {
|
||||
export type GameFieldStore = Readable<GameFieldState> & {tick: (inputs: Input[], dt: number) => void, update: (objects: GameObject[], state: GameState) => void};
|
||||
|
||||
function createGameFieldStore(): GameFieldStore {
|
||||
const {subscribe, set} = writable<GameFieldState>({ts: 0, objects: [], state: {score: {player1: 0, player2: 0}}});
|
||||
const {subscribe, set} = writable<GameFieldState>({ts: 0, objects: [], state: {score: {player_1: 0, player_2: 0}}});
|
||||
|
||||
const field = FieldWrapper.new();
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import type {GameObject, NetworkSession, Session} from "./session";
|
||||
import type {GameObject, GameState, NetworkSession, Session} from "./session";
|
||||
import type {Input} from "./input";
|
||||
|
||||
export type SessionEventPayload = {
|
||||
@@ -28,6 +28,11 @@ export type TickEventPayload = {
|
||||
ts: number
|
||||
}
|
||||
|
||||
export type StatusEventPayload = {
|
||||
session_id: string,
|
||||
state: GameState
|
||||
}
|
||||
|
||||
export type SessionEvenWrapper = {
|
||||
topic: 'session',
|
||||
event: SessionEventPayload
|
||||
@@ -48,7 +53,12 @@ export type MoveEventWrapper = {
|
||||
event: GameObject
|
||||
}
|
||||
|
||||
export type GameEventWrapper = SessionEvenWrapper | InputEventWrapper | MoveEventWrapper | TickEventWrapper;
|
||||
export type StatusEventWrapper = {
|
||||
topic: 'status',
|
||||
event: StatusEventPayload
|
||||
}
|
||||
|
||||
export type GameEventWrapper = SessionEvenWrapper | InputEventWrapper | MoveEventWrapper | TickEventWrapper | StatusEventWrapper;
|
||||
|
||||
export const isSessionEvent = (event: GameEventWrapper): event is SessionEvenWrapper => {
|
||||
return event.topic === 'session';
|
||||
@@ -65,3 +75,7 @@ export const isMoveEvent = (event: GameEventWrapper): event is MoveEventWrapper
|
||||
export const isTickEvent = (event: GameEventWrapper): event is TickEventWrapper => {
|
||||
return event.topic === 'tick';
|
||||
}
|
||||
|
||||
export const isStatusEvent = (event: GameEventWrapper): event is StatusEventWrapper => {
|
||||
return event.topic === 'status';
|
||||
}
|
||||
|
||||
@@ -63,8 +63,8 @@ export function isLocalSession(session: Session): session is LocalSession {
|
||||
}
|
||||
|
||||
export type GameScore = {
|
||||
player1: number,
|
||||
player2: number,
|
||||
player_1: number,
|
||||
player_2: number,
|
||||
}
|
||||
|
||||
export type GameState = {
|
||||
|
||||
@@ -1,15 +1,21 @@
|
||||
import {derived, get, Readable, readable, Unsubscriber, writable} from "svelte/store";
|
||||
import api from "../api/session";
|
||||
import type {LocalSession, Message, NetworkSession, Session, SessionSnapshot} from "./model/session";
|
||||
import type {GameState, LocalSession, Message, NetworkSession, Session, SessionSnapshot} from "./model/session";
|
||||
import {isLocalSession, isNetworkSession, MessageType, SessionState, SessionType} from "./model/session";
|
||||
import type {NetworkStore} from "./network";
|
||||
import type {GameEventWrapper, InputEventPayload, SessionEventPayload, TickEventPayload} from "./model/event";
|
||||
import {isInputEvent, isMoveEvent, isSessionEvent, isTickEvent} from "./model/event";
|
||||
import type {
|
||||
GameEventWrapper,
|
||||
InputEventPayload,
|
||||
SessionEventPayload,
|
||||
StatusEventPayload,
|
||||
TickEventPayload
|
||||
} from "./model/event";
|
||||
import {isInputEvent, isMoveEvent, isSessionEvent, isStatusEvent, isTickEvent} from "./model/event";
|
||||
import {getPlayerKeyboardInputs, playerKeyboardInputs} from "./input";
|
||||
import type {Subscriber} from "svelte/types/runtime/store";
|
||||
import {combined} from "./utils";
|
||||
import type {Input} from "./model/input";
|
||||
import {init, tick} from "svelte/internal";
|
||||
import {init, subscribe, tick} from "svelte/internal";
|
||||
|
||||
const sessionStore = writable<Session>(null);
|
||||
|
||||
@@ -134,6 +140,30 @@ export const networkSessionStateEvents = readable<SessionEventPayload[]>([], set
|
||||
}
|
||||
});
|
||||
|
||||
export const gameStateEvents = (function() {
|
||||
const lastEvent = writable<StatusEventPayload>(null);
|
||||
const unsubNetworkEvents = networkEvents.subscribe($events => {
|
||||
const events = $events.filter(isStatusEvent);
|
||||
if (!events.length) {
|
||||
return;
|
||||
}
|
||||
const latest = events[events.length - 1];
|
||||
lastEvent.set(latest.event);
|
||||
})
|
||||
|
||||
const customSubscribe = (run: Subscriber<StatusEventPayload>, invalidate): Unsubscriber => {
|
||||
const unsub = lastEvent.subscribe(run, invalidate);
|
||||
return () => {
|
||||
unsub();
|
||||
unsubNetworkEvents();
|
||||
}
|
||||
}
|
||||
|
||||
return {
|
||||
subscribe: customSubscribe
|
||||
}
|
||||
}())
|
||||
|
||||
export type NetworkTickEventState = {
|
||||
hasNext: boolean;
|
||||
events: TickEventPayload[]
|
||||
|
||||
@@ -29,7 +29,7 @@ pub enum PongEvent {
|
||||
#[derive(Debug, Serialize, Deserialize)]
|
||||
pub struct MoveEventPayload {
|
||||
pub session_id: String,
|
||||
pub id: i32,
|
||||
pub id: String,
|
||||
pub orientation_x: f64,
|
||||
pub orientation_y: f64,
|
||||
pub shape_param_1: f64,
|
||||
|
||||
@@ -455,7 +455,7 @@ struct ObserverSessionSnapshotDTO {
|
||||
|
||||
#[derive(Deserialize)]
|
||||
struct GameObjectStateDTO {
|
||||
pub id: i32,
|
||||
pub id: String,
|
||||
pub orientation_x: f64,
|
||||
pub orientation_y: f64,
|
||||
pub shape_param_1: f64,
|
||||
@@ -471,7 +471,7 @@ impl GameObjectStateDTO {
|
||||
MoveEventPayload {
|
||||
session_id: session_id.to_owned(),
|
||||
ts,
|
||||
id: self.id,
|
||||
id: self.id.clone(),
|
||||
x: self.x,
|
||||
y: self.y,
|
||||
orientation_x: self.orientation_x,
|
||||
|
||||
Reference in New Issue
Block a user