taiko-web development has returned to GitHub. This Gitea instance will be shut down soon.
If your taiko-web fork is unavailable due to DMCA takedown, you can contact GitHub Support and ask for it to be deleted.
Browse Source

SongBg: Add song skins

kekero 2 months ago
parent
commit
e43821ba48
6 changed files with 135 additions and 57 deletions
  1. 2
    1
      .gitignore
  2. 11
    1
      app.py
  3. 9
    0
      public/src/css/songbg.css
  4. 86
    46
      public/src/js/loadsong.js
  5. 4
    2
      public/src/js/songselect.js
  6. 23
    7
      public/src/js/view.js

+ 2
- 1
.gitignore View File

@@ -46,4 +46,5 @@ public/api
46 46
 taiko.db
47 47
 version.json
48 48
 public/index.html
49
-config.json
49
+config.json
50
+public/assets/song_skins

+ 11
- 1
app.py View File

@@ -154,17 +154,26 @@ def route_api_preview():
154 154
 @app.route('/api/songs')
155 155
 def route_api_songs():
156 156
     songs = query_db('select * from songs where enabled = 1')
157
+    
157 158
     raw_categories = query_db('select * from categories')
158 159
     categories = {}
159 160
     def_category = {'title': None, 'title_en': None}
160 161
     for cat in raw_categories:
161 162
         categories[cat[0]] = {'title': cat[1], 'title_en': cat[2]}
163
+    
164
+    raw_song_skins = query_db('select * from song_skins')
165
+    song_skins = {}
166
+    for skin in raw_song_skins:
167
+        song_skins[skin[0]] = {'name': skin[1], 'song': skin[2], 'stage': skin[3]}
168
+    
162 169
     songs_out = []
163 170
     for song in songs:
164 171
         song_id = song[0]
165 172
         song_type = song[12]
166 173
         preview = get_preview(song_id, song_type)
174
+        
167 175
         category_out = categories[song[11]] if song[11] in categories else def_category
176
+        song_skin_out = song_skins[song[14]] if song[14] in categories else None
168 177
         
169 178
         songs_out.append({
170 179
             'id': song_id,
@@ -179,7 +188,8 @@ def route_api_songs():
179 188
             'category': category_out['title'],
180 189
             'category_en': category_out['title_en'],
181 190
             'type': song_type,
182
-            'offset': song[13]
191
+            'offset': song[13],
192
+            'song_skin': song_skin_out
183 193
         })
184 194
 
185 195
     return jsonify(songs_out)

+ 9
- 0
public/src/css/songbg.css View File

@@ -67,6 +67,15 @@
67 67
 	animation: 1s linear songbg-pulse infinite;
68 68
 	mix-blend-mode: color-dodge;
69 69
 }
70
+.songbg-strobe #layer2{
71
+	animation: 0.4s linear songbg-strobe infinite;
72
+}
73
+.songbg-pulse #layer2{
74
+	animation: 0.4s linear songbg-pulse infinite;
75
+}
76
+.songbg-slowfade #layer2{
77
+	animation: 2s cubic-bezier(0.68, -0.55, 0.27, 1.55) songbg-pulse infinite;
78
+}
70 79
 .touch-visible #layer2{
71 80
 	display: none;
72 81
 	background-image: none;

+ 86
- 46
public/src/js/loadsong.js View File

@@ -4,26 +4,60 @@ class loadSong{
4 4
 		this.autoPlayEnabled = autoPlayEnabled
5 5
 		this.multiplayer = multiplayer
6 6
 		this.touchEnabled = touchEnabled
7
+		
7 8
 		loader.changePage("loadsong")
8 9
 		this.run()
9 10
 	}
10 11
 	run(){
11
-		var id = this.selectedSong.folder
12
+		var song = this.selectedSong
13
+		var id = song.folder
12 14
 		var promises = []
13 15
 		assets.sounds["start"].play()
14 16
 		
15
-		this.selectedSong.songBg = this.randInt(1, 5)
16
-		this.selectedSong.songStage = this.randInt(1, 3)
17
-		
18
-		promises.push(new Promise(resolve => {
19
-			var img = document.createElement("img")
20
-			pageEvents.load(img).then(() => {
21
-				this.selectedSong.customBg = true
22
-			}, () => this.songBg(id)).then(resolve)
23
-			img.id = "music-bg"
24
-			img.src = gameConfig.songs_baseurl + id + "/bg.png"
25
-			document.getElementById("assets").appendChild(img)
26
-		}))
17
+		song.songBg = this.randInt(1, 5)
18
+		song.songStage = this.randInt(1, 3)
19
+		if(song.songSkin && song.songSkin.name){
20
+			var imgLoad = []
21
+			for(var type in song.songSkin){
22
+				var value = song.songSkin[type]
23
+				if(type !== "name" && value && value !== "none"){
24
+					var filename = "bg_" + type + "_" + song.songSkin.name
25
+					if(value === "static"){
26
+						imgLoad.push({
27
+							filename: filename,
28
+							type: type
29
+						})
30
+					}else{
31
+						imgLoad.push({
32
+							filename: filename + "_a",
33
+							type: type
34
+						})
35
+						imgLoad.push({
36
+							filename: filename + "_b",
37
+							type: type
38
+						})
39
+					}
40
+				}
41
+			}
42
+			var skinBase = gameConfig.assets_baseurl + "song_skins/"
43
+			for(var i = 0; i < imgLoad.length; i++){
44
+				let img = document.createElement("img")
45
+				let filename = imgLoad[i].filename
46
+				let promise = pageEvents.load(img)
47
+				if(imgLoad[i].type === "song"){
48
+					promises.push(promise.then(() => {
49
+						return this.scaleImg(img, filename)
50
+					}))
51
+				}else{
52
+					promises.push(promise.then(() => {
53
+						assets.image[filename] = img
54
+					}))
55
+				}
56
+				img.src = skinBase + filename + ".png"
57
+			}
58
+		}else{
59
+			promises.push(this.songBg(id))
60
+		}
27 61
 		
28 62
 		promises.push(new Promise((resolve, reject) => {
29 63
 			var songObj
@@ -42,7 +76,7 @@ class loadSong{
42 76
 				}, reject)
43 77
 			}
44 78
 		}))
45
-		promises.push(loader.ajax(this.getSongPath(this.selectedSong)).then(data => {
79
+		promises.push(loader.ajax(this.getSongPath(song)).then(data => {
46 80
 			this.songData = data.replace(/\0/g, "").split("\n")
47 81
 		}))
48 82
 		Promise.all(promises).then(() => {
@@ -63,27 +97,7 @@ class loadSong{
63 97
 					let filenameAb = filename + (i === 0 ? "a" : "b")
64 98
 					let img = document.createElement("img")
65 99
 					promises.push(pageEvents.load(img).then(() => {
66
-						if(this.touchEnabled){
67
-							return new Promise((resolve, reject) => {
68
-								var canvas = document.createElement("canvas")
69
-								var w = Math.floor(img.width / 2)
70
-								var h = Math.floor(img.height / 2)
71
-								canvas.width = w
72
-								canvas.height = h
73
-								var ctx = canvas.getContext("2d")
74
-								ctx.drawImage(img, 0, 0, w, h)
75
-								canvas.toBlob(blob => {
76
-									let img2 = document.createElement("img")
77
-									pageEvents.load(img2).then(() => {
78
-										assets.image[filenameAb] = img2
79
-										resolve()
80
-									}, reject)
81
-									img2.src = URL.createObjectURL(blob)
82
-								})
83
-							})
84
-						}else{
85
-							assets.image[filenameAb] = img
86
-						}
100
+						return this.scaleImg(img, filenameAb)
87 101
 					}))
88 102
 					img.src = gameConfig.assets_baseurl + "img/" + filenameAb + ".png"
89 103
 				}
@@ -91,6 +105,30 @@ class loadSong{
91 105
 			}
92 106
 		})
93 107
 	}
108
+	scaleImg(img, filename){
109
+		return new Promise((resolve, reject) => {
110
+			if(this.touchEnabled){
111
+				var canvas = document.createElement("canvas")
112
+				var w = Math.floor(img.width / 2)
113
+				var h = Math.floor(img.height / 2)
114
+				canvas.width = w
115
+				canvas.height = h
116
+				var ctx = canvas.getContext("2d")
117
+				ctx.drawImage(img, 0, 0, w, h)
118
+				canvas.toBlob(blob => {
119
+					let img2 = document.createElement("img")
120
+					pageEvents.load(img2).then(() => {
121
+						assets.image[filename] = img2
122
+						resolve()
123
+					}, reject)
124
+					img2.src = URL.createObjectURL(blob)
125
+				})
126
+			}else{
127
+				assets.image[filename] = img
128
+				resolve()
129
+			}
130
+		})
131
+	}
94 132
 	randInt(min, max){
95 133
 		return Math.floor(Math.random() * (max - min + 1)) + min
96 134
 	}
@@ -103,6 +141,8 @@ class loadSong{
103 141
 		}
104 142
 	}
105 143
 	setupMultiplayer(){
144
+		var song = this.selectedSong
145
+		
106 146
 		if(this.multiplayer){
107 147
 			var loadingText = document.getElementsByClassName("loading-text")[0]
108 148
 			var waitingText = "Waiting for Another Player..."
@@ -114,22 +154,22 @@ class loadSong{
114 154
 			pageEvents.add(this.cancelButton, ["mousedown", "touchstart"], this.cancelLoad.bind(this))
115 155
 			
116 156
 			this.song2Data = this.songData
117
-			this.selectedSong2 = this.selectedSong
157
+			this.selectedSong2 = song
118 158
 			pageEvents.add(p2, "message", event => {
119 159
 				if(event.type === "gameload"){
120 160
 					this.cancelButton.style.display = ""
121 161
 					
122
-					if(event.value === this.selectedSong.difficulty){
162
+					if(event.value === song.difficulty){
123 163
 						this.startMultiplayer()
124 164
 					}else{
125 165
 						this.selectedSong2 = {
126
-							title: this.selectedSong.title,
127
-							folder: this.selectedSong.folder,
166
+							title: song.title,
167
+							folder: song.folder,
128 168
 							difficulty: event.value,
129
-							type: this.selectedSong.type,
130
-							offset: this.selectedSong.offset
169
+							type: song.type,
170
+							offset: song.offset
131 171
 						}
132
-						if(this.selectedSong.type === "tja"){
172
+						if(song.type === "tja"){
133 173
 							this.startMultiplayer()
134 174
 						}else{
135 175
 							loader.ajax(this.getSongPath(this.selectedSong2)).then(data => {
@@ -144,7 +184,7 @@ class loadSong{
144 184
 					this.clean()
145 185
 					p2.clearMessage("songsel")
146 186
 					loader.changePage("game")
147
-					var taikoGame1 = new Controller(this.selectedSong, this.songData, false, 1, this.touchEnabled)
187
+					var taikoGame1 = new Controller(song, this.songData, false, 1, this.touchEnabled)
148 188
 					var taikoGame2 = new Controller(this.selectedSong2, this.song2Data, true, 2, this.touchEnabled)
149 189
 					taikoGame1.run(taikoGame2)
150 190
 				}else if(event.type === "left" || event.type === "gameend"){
@@ -153,13 +193,13 @@ class loadSong{
153 193
 				}
154 194
 			})
155 195
 			p2.send("join", {
156
-				id: this.selectedSong.folder,
157
-				diff: this.selectedSong.difficulty
196
+				id: song.folder,
197
+				diff: song.difficulty
158 198
 			})
159 199
 		}else{
160 200
 			this.clean()
161 201
 			loader.changePage("game")
162
-			var taikoGame = new Controller(this.selectedSong, this.songData, this.autoPlayEnabled, false, this.touchEnabled)
202
+			var taikoGame = new Controller(song, this.songData, this.autoPlayEnabled, false, this.touchEnabled)
163 203
 			taikoGame.run()
164 204
 		}
165 205
 	}

+ 4
- 2
public/src/js/songselect.js View File

@@ -97,7 +97,8 @@ class SongSelect{
97 97
 				category: song.category,
98 98
 				preview: song.preview || 0,
99 99
 				type: song.type,
100
-				offset: song.offset
100
+				offset: song.offset,
101
+				songSkin: song.song_skin
101 102
 			})
102 103
 		}
103 104
 		this.songs.sort((a, b) => {
@@ -614,7 +615,8 @@ class SongSelect{
614 615
 			"difficulty": this.difficultyId[difficulty],
615 616
 			"category": selectedSong.category,
616 617
 			"type": selectedSong.type,
617
-			"offset": selectedSong.offset
618
+			"offset": selectedSong.offset,
619
+			"songSkin": selectedSong.songSkin
618 620
 		}, autoplay, multiplayer, touch)
619 621
 	}
620 622
 	toOptions(moveBy){

+ 23
- 7
public/src/js/view.js View File

@@ -960,6 +960,8 @@
960 960
 		var songStage = document.getElementById("song-stage")
961 961
 		
962 962
 		var selectedSong = this.controller.selectedSong
963
+		var songSkinName = selectedSong.songSkin.name
964
+		
963 965
 		if(selectedSong.category in this.categories){
964 966
 			var catId = this.categories[selectedSong.category].sort
965 967
 		}else{
@@ -967,17 +969,31 @@
967 969
 		}
968 970
 		this.setBgImage(this.gameDiv, assets.image["bg_genre_" + catId].src)
969 971
 		
970
-		if(selectedSong.customBg){
971
-			var bg = gameConfig.songs_baseurl + selectedSong.folder + "/bg.png"
972
-			this.setBgImage(songBg, bg)
973
-		}else{
972
+		if(!selectedSong.songSkin.song){
974 973
 			var id = selectedSong.songBg
975 974
 			songBg.classList.add("songbg-" + id)
976
-			this.setBgImage(document.getElementById("layer1"), assets.image["bg_song_" + id + "a"].src)
977
-			this.setBgImage(document.getElementById("layer2"), assets.image["bg_song_" + id + "b"].src)
975
+			this.setLayers("bg_song_" + id, true)
976
+		}else if(selectedSong.songSkin.song !== "none"){
977
+			var notStatic = selectedSong.songSkin.song !== "static"
978
+			if(notStatic){
979
+				songBg.classList.add("songbg-" + selectedSong.songSkin.song)
980
+			}
981
+			this.setLayers("bg_song_" + songSkinName + (notStatic ? "_" : ""), notStatic)
978 982
 		}
979 983
 		
980
-		songStage.classList.add("song-stage-" + selectedSong.songStage)
984
+		if(!selectedSong.songSkin.stage){
985
+			songStage.classList.add("song-stage-" + selectedSong.songStage)
986
+		}else if(selectedSong.songSkin.stage !== "none"){
987
+			this.setBgImage(songStage, assets.image["bg_stage_" + songSkinName].src)
988
+		}
989
+	}
990
+	setLayers(file, ab){
991
+		if(ab){
992
+			this.setBgImage(document.getElementById("layer1"), assets.image[file + "a"].src)
993
+			this.setBgImage(document.getElementById("layer2"), assets.image[file + "b"].src)
994
+		}else{
995
+			this.setBgImage(document.getElementById("layer1"), assets.image[file].src)
996
+		}
981 997
 	}
982 998
 	setBgImage(element, url){
983 999
 		element.style.backgroundImage = "url('" + url + "')"

Loading…
Cancel
Save