@kennofizet/rewardplay-frontend 1.0.4 → 1.0.6

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (46) hide show
  1. package/README.md +18 -1
  2. package/package.json +2 -2
  3. package/src/components/MainGame.vue +3 -1
  4. package/src/components/game/TopMenu.vue +4 -0
  5. package/src/components/game/rpg/MapEditor.vue +247 -0
  6. package/src/components/game/rpg/RPGGame.vue +2660 -0
  7. package/src/components/game/rpg/botAI.js +332 -0
  8. package/src/components/game/rpg/data/bosses.js +98 -0
  9. package/src/components/game/rpg/data/classes.js +267 -0
  10. package/src/components/game/rpg/data/dungeonGenerator.js +119 -0
  11. package/src/components/game/rpg/data/eclipseClasses.js +186 -0
  12. package/src/components/game/rpg/data/enemies.js +230 -0
  13. package/src/components/game/rpg/data/farmData.js +301 -0
  14. package/src/components/game/rpg/data/items.js +218 -0
  15. package/src/components/game/rpg/data/maps.js +966 -0
  16. package/src/components/game/rpg/data/npcs.js +250 -0
  17. package/src/components/game/rpg/entity.js +128 -0
  18. package/src/components/game/rpg/farmEngine.js +1838 -0
  19. package/src/components/game/rpg/gameEngine.js +2070 -0
  20. package/src/components/game/rpg/skillEffects/SkillEffectBase.js +301 -0
  21. package/src/components/game/rpg/skillEffects/aoeCircle.js +110 -0
  22. package/src/components/game/rpg/skillEffects/blinkFlash.js +52 -0
  23. package/src/components/game/rpg/skillEffects/buffAura.js +64 -0
  24. package/src/components/game/rpg/skillEffects/castFlash.js +32 -0
  25. package/src/components/game/rpg/skillEffects/coneBlast.js +126 -0
  26. package/src/components/game/rpg/skillEffects/debuffWave.js +65 -0
  27. package/src/components/game/rpg/skillEffects/earthquake.js +119 -0
  28. package/src/components/game/rpg/skillEffects/fadeOut.js +33 -0
  29. package/src/components/game/rpg/skillEffects/healRing.js +51 -0
  30. package/src/components/game/rpg/skillEffects/index.js +22 -0
  31. package/src/components/game/rpg/skillEffects/lifesteal.js +57 -0
  32. package/src/components/game/rpg/skillEffects/lightning.js +111 -0
  33. package/src/components/game/rpg/skillEffects/lineBlast.js +122 -0
  34. package/src/components/game/rpg/skillEffects/meteor.js +154 -0
  35. package/src/components/game/rpg/skillEffects/novaRing.js +82 -0
  36. package/src/components/game/rpg/skillEffects/slashArc.js +121 -0
  37. package/src/components/game/rpg/skillEffects/summonCircle.js +65 -0
  38. package/src/components/game/rpg/skillEffects/tornado.js +119 -0
  39. package/src/components/game/rpg/skillEffects.js +64 -0
  40. package/src/components/game/rpg/sprites.js +1571 -0
  41. package/src/components/game/rpg/tiles.js +259 -0
  42. package/src/pages/game/ManageSettingPage.vue +3 -0
  43. package/src/pages/game/MapEditorPage.vue +17 -0
  44. package/src/pages/game/RPGGamePage.vue +17 -0
  45. package/src/pages/game/manage-setting/SettingMapEditorPage.vue +989 -0
  46. package/tools/generate_assets.js +737 -0
package/README.md CHANGED
@@ -96,7 +96,24 @@ onMounted(() => {
96
96
 
97
97
  Both are required when calling `app.use(RewardPlay, { backendUrl, token })`.
98
98
 
99
- ### 4. RewardPlayPage root props (optional)
99
+ ### 4. Vite: optimizeDeps
100
+
101
+ If you mount RewardPlay in a separate app with `createApp(RewardPlayPage).use(RewardPlay, { backendUrl, token }).mount(...)`, add the package to Vite’s `optimizeDeps.include` so it uses the same Vue instance and `inject('gameApi')` works:
102
+
103
+ ```js
104
+ // vite.config.js (or vite.config.ts)
105
+ export default {
106
+ // ...
107
+ optimizeDeps: {
108
+ include: ['@kennofizet/rewardplay-frontend'],
109
+ // ... rest of your config
110
+ },
111
+ }
112
+ ```
113
+
114
+ Without this, dev and build can end up with a different Vue instance for the package and `gameApi` may be missing (e.g. “gameApi.... is not a function”)
115
+
116
+ ### 5. RewardPlayPage root props (optional)
100
117
 
101
118
  | Prop | Type | Default | Description |
102
119
  |------------------|--------|--------|--------------------------------|
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@kennofizet/rewardplay-frontend",
3
- "version": "1.0.4",
3
+ "version": "1.0.6",
4
4
  "description": "RewardPlay frontend package - Token-based API client for RewardPlay",
5
5
  "main": "./src/index.js",
6
6
  "module": "./src/index.js",
@@ -49,4 +49,4 @@
49
49
  "engines": {
50
50
  "node": ">=16.0.0"
51
51
  }
52
- }
52
+ }
@@ -47,7 +47,9 @@ const pageMap = {
47
47
  'ranking': RankingPage,
48
48
  'rules': ComingSoonPage,
49
49
  'shop': ShopPage,
50
- 'manage-setting': ManageSettingPage
50
+ 'manage-setting': ManageSettingPage,
51
+ 'rpg-game': () => import('../pages/game/RPGGamePage.vue'),
52
+ 'map-editor': () => import('../pages/game/MapEditorPage.vue')
51
53
  }
52
54
 
53
55
  const currentPage = shallowRef(DailyRewardPage) // Default to DailyReward
@@ -12,6 +12,10 @@
12
12
  {{ t('component.menu.bag') }}
13
13
  </MenuItem>
14
14
 
15
+ <MenuItem @click="$emit('page-change', 'rpg-game')">
16
+ Game
17
+ </MenuItem>
18
+
15
19
  <MenuItem @click="$emit('page-change', 'ranking')">
16
20
  {{ t('component.menu.ranking') }}
17
21
  </MenuItem>
@@ -0,0 +1,247 @@
1
+ <template>
2
+ <div class="map-editor">
3
+ <div class="editor-sidebar">
4
+ <h3>Tools</h3>
5
+ <div class="tile-selector">
6
+ <div
7
+ v-for="(name, id) in tileNames"
8
+ :key="id"
9
+ class="tile-option"
10
+ :class="{ active: selectedTile == id }"
11
+ @click="selectedTile = parseInt(id)"
12
+ >
13
+ <div class="tile-preview" :style="{ backgroundColor: tileColors[id] }"></div>
14
+ <span>{{ name }}</span>
15
+ </div>
16
+ </div>
17
+
18
+ <div class="editor-actions">
19
+ <button @click="saveMap" class="btn-save">Save Map</button>
20
+ <button @click="loadMap" class="btn-load">Load Map</button>
21
+ <button @click="clearMap" class="btn-clear">Clear</button>
22
+ </div>
23
+ </div>
24
+
25
+ <div class="editor-canvas-container">
26
+ <canvas
27
+ ref="canvas"
28
+ @mousedown="startDrawing"
29
+ @mousemove="draw"
30
+ @mouseup="stopDrawing"
31
+ @mouseleave="stopDrawing"
32
+ ></canvas>
33
+ </div>
34
+ </div>
35
+ </template>
36
+
37
+ <script setup>
38
+ import { ref, onMounted, computed, watch } from 'vue'
39
+ import { TILE_SIZE, TILES, TILE_COLORS, TILE_NAMES } from './tiles'
40
+
41
+ const tileColors = TILE_COLORS
42
+ const tileNames = TILE_NAMES
43
+
44
+ const selectedTile = ref(TILES.GRASS)
45
+ const canvas = ref(null)
46
+ const isDrawing = ref(false)
47
+
48
+ // Map Data
49
+ const mapWidth = 30
50
+ const mapHeight = 20
51
+ const mapTiles = ref(new Array(mapWidth * mapHeight).fill(TILES.EMPTY))
52
+
53
+ let ctx = null
54
+
55
+ onMounted(() => {
56
+ if (canvas.value) {
57
+ canvas.value.width = mapWidth * TILE_SIZE
58
+ canvas.value.height = mapHeight * TILE_SIZE
59
+ ctx = canvas.value.getContext('2d')
60
+ render()
61
+ }
62
+ })
63
+
64
+ const render = () => {
65
+ if (!ctx) return
66
+
67
+ // Clear
68
+ ctx.fillStyle = '#111'
69
+ ctx.fillRect(0, 0, canvas.value.width, canvas.value.height)
70
+
71
+ // Draw Tiles
72
+ for (let i = 0; i < mapTiles.value.length; i++) {
73
+ const x = (i % mapWidth) * TILE_SIZE
74
+ const y = Math.floor(i / mapWidth) * TILE_SIZE
75
+
76
+ const tileId = mapTiles.value[i]
77
+ ctx.fillStyle = tileColors[tileId] || '#000'
78
+ ctx.fillRect(x, y, TILE_SIZE, TILE_SIZE)
79
+
80
+ // Grid
81
+ ctx.strokeStyle = '#333'
82
+ ctx.strokeRect(x, y, TILE_SIZE, TILE_SIZE)
83
+ }
84
+ }
85
+
86
+ const getTileIndex = (event) => {
87
+ const rect = canvas.value.getBoundingClientRect()
88
+ const x = Math.floor((event.clientX - rect.left) / TILE_SIZE)
89
+ const y = Math.floor((event.clientY - rect.top) / TILE_SIZE)
90
+
91
+ if (x >= 0 && x < mapWidth && y >= 0 && y < mapHeight) {
92
+ return y * mapWidth + x
93
+ }
94
+ return -1
95
+ }
96
+
97
+ const startDrawing = (event) => {
98
+ isDrawing.value = true
99
+ placeTile(event)
100
+ }
101
+
102
+ const draw = (event) => {
103
+ if (isDrawing.value) {
104
+ placeTile(event)
105
+ }
106
+ }
107
+
108
+ const stopDrawing = () => {
109
+ isDrawing.value = false
110
+ }
111
+
112
+ const placeTile = (event) => {
113
+ const index = getTileIndex(event)
114
+ if (index !== -1) {
115
+ mapTiles.value[index] = selectedTile.value
116
+ render()
117
+ }
118
+ }
119
+
120
+ const saveMap = () => {
121
+ const mapData = {
122
+ width: mapWidth,
123
+ height: mapHeight,
124
+ tiles: mapTiles.value
125
+ }
126
+ localStorage.setItem('rpg_map_data', JSON.stringify(mapData))
127
+ alert('Map saved to LocalStorage!')
128
+ }
129
+
130
+ const loadMap = () => {
131
+ const saved = localStorage.getItem('rpg_map_data')
132
+ if (saved) {
133
+ try {
134
+ const data = JSON.parse(saved)
135
+ if (data.tiles && data.tiles.length === mapWidth * mapHeight) {
136
+ mapTiles.value = data.tiles
137
+ render()
138
+ alert('Map loaded!')
139
+ } else {
140
+ alert('Saved map size mismatch.')
141
+ }
142
+ } catch (e) {
143
+ console.error(e)
144
+ }
145
+ } else {
146
+ alert('No saved map found.')
147
+ }
148
+ }
149
+
150
+ const clearMap = () => {
151
+ if (confirm('Are you sure you want to clear the map?')) {
152
+ mapTiles.value = new Array(mapWidth * mapHeight).fill(TILES.EMPTY)
153
+ render()
154
+ }
155
+ }
156
+ </script>
157
+
158
+ <style scoped>
159
+ .map-editor {
160
+ display: flex;
161
+ height: 100%;
162
+ padding: 20px;
163
+ gap: 20px;
164
+ color: #fff;
165
+ }
166
+
167
+ .editor-sidebar {
168
+ width: 250px;
169
+ background: rgba(0,0,0,0.5);
170
+ padding: 15px;
171
+ border-radius: 8px;
172
+ display: flex;
173
+ flex-direction: column;
174
+ }
175
+
176
+ .tile-selector {
177
+ flex: 1;
178
+ overflow-y: auto;
179
+ margin: 15px 0;
180
+ display: flex;
181
+ flex-direction: column;
182
+ gap: 8px;
183
+ }
184
+
185
+ .tile-option {
186
+ display: flex;
187
+ align-items: center;
188
+ gap: 10px;
189
+ padding: 8px;
190
+ cursor: pointer;
191
+ border-radius: 4px;
192
+ transition: background 0.2s;
193
+ }
194
+
195
+ .tile-option:hover {
196
+ background: rgba(255,255,255,0.1);
197
+ }
198
+
199
+ .tile-option.active {
200
+ background: rgba(33, 150, 243, 0.3);
201
+ border: 1px solid #2196f3;
202
+ }
203
+
204
+ .tile-preview {
205
+ width: 24px;
206
+ height: 24px;
207
+ border: 1px solid rgba(255,255,255,0.2);
208
+ }
209
+
210
+ .editor-actions {
211
+ display: flex;
212
+ flex-direction: column;
213
+ gap: 10px;
214
+ }
215
+
216
+ .editor-actions button {
217
+ padding: 10px;
218
+ border: none;
219
+ border-radius: 4px;
220
+ cursor: pointer;
221
+ font-weight: bold;
222
+ transition: opacity 0.2s;
223
+ }
224
+
225
+ .editor-actions button:hover {
226
+ opacity: 0.9;
227
+ }
228
+
229
+ .btn-save { background: #4caf50; color: white; }
230
+ .btn-load { background: #2196f3; color: white; }
231
+ .btn-clear { background: #f44336; color: white; }
232
+
233
+ .editor-canvas-container {
234
+ flex: 1;
235
+ background: #1a1a1a;
236
+ display: flex;
237
+ justify-content: center;
238
+ align-items: center;
239
+ border-radius: 8px;
240
+ overflow: auto;
241
+ }
242
+
243
+ canvas {
244
+ background: #000;
245
+ box-shadow: 0 0 20px rgba(0,0,0,0.5);
246
+ }
247
+ </style>