Go で書き直した Ikemen
修订版 | 9e140f37a85e2800a17cccde72623e3d4d53dc28 (tree) |
---|---|
时间 | 2019-10-26 18:58:56 |
作者 | neatunsou <sisiy4excite@gmai...> |
Commiter | neatunsou |
Windblade氏の更新に対応
@@ -397,9 +397,9 @@ function options.f_mainCfg() | ||
397 | 397 | elseif t[item].itemname == 'defaultvalues' then |
398 | 398 | sndPlay(motif.files.snd_data, motif.option_info.cursor_done_snd[1], motif.option_info.cursor_done_snd[2]) |
399 | 399 | config.HelperMax = 56 |
400 | - config.PlayerProjectileMax = 50 | |
401 | - config.ExplodMax = 256 | |
402 | - config.AfterImageMax = 8 | |
400 | + config.PlayerProjectileMax = 256 | |
401 | + config.ExplodMax = 512 | |
402 | + config.AfterImageMax = 128 | |
403 | 403 | config['Attack.LifeToPowerMul'] = 0.7 |
404 | 404 | config['GetHit.LifeToPowerMul'] = 0.6 |
405 | 405 | config.Width = 640 |
@@ -827,7 +827,7 @@ getSpriteInfo('chars/kfm/kfm.sff', 0, 1) | ||
827 | 827 | end |
828 | 828 | --victory screen |
829 | 829 | if main.gameMode == 'arcade' or main.gameMode == 'teamcoop' or main.gameMode == 'netplayteamcoop' then |
830 | - if main.t_selChars[t_p2Selected[1].cel + 1].winscreen == nil or main.t_selChars[t_p2Selected[1].cel + 1].winscreen == 1 then | |
830 | + if motif.victory_screen.enabled == 1 and (main.t_selChars[t_p2Selected[1].cel + 1].winscreen == nil or main.t_selChars[t_p2Selected[1].cel + 1].winscreen == 1) then | |
831 | 831 | select.f_selectVictory() |
832 | 832 | end |
833 | 833 | end |
@@ -869,7 +869,7 @@ getSpriteInfo('chars/kfm/kfm.sff', 0, 1) | ||
869 | 869 | looseCnt = looseCnt + 1 |
870 | 870 | --victory screen |
871 | 871 | if main.gameMode == 'arcade' or main.gameMode == 'teamcoop' or main.gameMode == 'netplayteamcoop' then |
872 | - if winner >= 1 and (main.t_selChars[t_p2Selected[1].cel + 1].winscreen == nil or main.t_selChars[t_p2Selected[1].cel + 1].winscreen == 1) then | |
872 | + if motif.victory_screen.enabled == 1 and winner >= 1 and (main.t_selChars[t_p2Selected[1].cel + 1].winscreen == nil or main.t_selChars[t_p2Selected[1].cel + 1].winscreen == 1) then | |
873 | 873 | select.f_selectVictory() |
874 | 874 | end |
875 | 875 | end |
@@ -890,7 +890,7 @@ getSpriteInfo('chars/kfm/kfm.sff', 0, 1) | ||
890 | 890 | --counter |
891 | 891 | looseCnt = looseCnt + 1 |
892 | 892 | --victory screen |
893 | - if winner >= 1 and (main.t_selChars[t_p2Selected[1].cel + 1].winscreen == nil or main.t_selChars[t_p2Selected[1].cel + 1].winscreen == 1) then | |
893 | + if motif.victory_screen.enabled == 1 and winner >= 1 and (main.t_selChars[t_p2Selected[1].cel + 1].winscreen == nil or main.t_selChars[t_p2Selected[1].cel + 1].winscreen == 1) then | |
894 | 894 | select.f_selectVictory() |
895 | 895 | end |
896 | 896 | --continue screen |
@@ -2540,12 +2540,9 @@ local txt_credits = main.f_createTextImg( | ||
2540 | 2540 | ) |
2541 | 2541 | |
2542 | 2542 | function select.f_continue() |
2543 | - main.f_resetBG(motif.continue_screen, motif.continuebgdef, motif.music.continue_bgm, motif.music.continue_bgm_loop, motif.music.continue_bgm_volume, motif.music.continue_bgm_loopstart, motif.music.continue_bgm_loopend) | |
2544 | - animReset(motif.continue_screen.continue_anim_data) | |
2545 | - animUpdate(motif.continue_screen.continue_anim_data) | |
2546 | 2543 | continue = false |
2547 | - local text = main.f_extractText(motif.continue_screen.credits_text, main.credits) | |
2548 | - textImgSetText(txt_credits, text[1]) | |
2544 | + playBGM(motif.music.continue_bgm, true, motif.music.continue_bgm_loop, motif.music.continue_bgm_volume, motif.music.continue_bgm_loopstart or "0", motif.music.continue_bgm_loopend or "0") | |
2545 | + --textImgSetText(txt_credits, text[1]) | |
2549 | 2546 | main.f_cmdInput() |
2550 | 2547 | while true do |
2551 | 2548 | --draw clearcolor (disabled to not cover area) |
@@ -3704,6 +3704,7 @@ func (sc projectile) Run(c *Char, _ []int32) bool { | ||
3704 | 3704 | p.hits = exp[0].evalI(c) |
3705 | 3705 | case projectile_projpriority: |
3706 | 3706 | p.priority = exp[0].evalI(c) |
3707 | + p.priorityPoints = p.priority | |
3707 | 3708 | case projectile_projhitanim: |
3708 | 3709 | p.hitanim = exp[0].evalI(c) |
3709 | 3710 | case projectile_projremanim: |
@@ -1103,7 +1103,7 @@ type Projectile struct { | ||
1103 | 1103 | hits int32 |
1104 | 1104 | misstime int32 |
1105 | 1105 | priority int32 |
1106 | - prioritypoint int32 | |
1106 | + priorityPoints int32 | |
1107 | 1107 | sprpriority int32 |
1108 | 1108 | edgebound int32 |
1109 | 1109 | stagebound int32 |
@@ -1138,7 +1138,7 @@ func (p *Projectile) clear() { | ||
1138 | 1138 | *p = Projectile{id: IErr, hitanim: -1, remanim: IErr, cancelanim: IErr, |
1139 | 1139 | scale: [...]float32{1, 1}, clsnScale: [...]float32{1, 1}, remove: true, localscl: 1, |
1140 | 1140 | removetime: -1, velmul: [...]float32{1, 1}, hits: 1, priority: 1, |
1141 | - prioritypoint: 1, sprpriority: 3, edgebound: 40, stagebound: 40, | |
1141 | + priorityPoints: 1, sprpriority: 3, edgebound: 40, stagebound: 40, | |
1142 | 1142 | heightbound: [...]int32{-240, 1}, facing: 1, aimg: *newAfterImage(), platformFence: true} |
1143 | 1143 | p.hitdef.clear() |
1144 | 1144 | } |
@@ -1235,27 +1235,19 @@ func (p *Projectile) clsn(playerNo int) { | ||
1235 | 1235 | if p.ani == nil || len(p.ani.frames) == 0 { |
1236 | 1236 | return |
1237 | 1237 | } |
1238 | - cancel := func(prioritypoint *int32, priority int32, hits *int32, | |
1239 | - oppprioritypoint int32) { | |
1240 | - if oppprioritypoint > *prioritypoint || *hits <= 0 { | |
1241 | - *hits = -2 | |
1242 | - return | |
1243 | - } | |
1244 | - if oppprioritypoint == *prioritypoint { | |
1245 | - if *hits <= 1 { | |
1246 | - *hits = -2 | |
1247 | - } else { | |
1248 | - *hits = int32(int64(*hits)*3/4 - 1) | |
1249 | - if *hits <= 0 { | |
1250 | - (*prioritypoint)-- | |
1251 | - } else { | |
1252 | - *prioritypoint = priority | |
1253 | - } | |
1254 | - } | |
1238 | + | |
1239 | + cancel := func(priorityPoints *int32, hits *int32, oppPriorityPoints int32) { | |
1240 | + if *priorityPoints > oppPriorityPoints { | |
1241 | + (*priorityPoints)-- | |
1255 | 1242 | } else { |
1256 | - (*prioritypoint)-- | |
1243 | + (*hits)-- | |
1244 | + } | |
1245 | + | |
1246 | + if *hits <= 0 { | |
1247 | + *hits = -2 | |
1257 | 1248 | } |
1258 | 1249 | } |
1250 | + | |
1259 | 1251 | for i := 0; i < playerNo && p.hits >= 0; i++ { |
1260 | 1252 | for j, pr := range sys.projs[i] { |
1261 | 1253 | if pr.hits < 0 || pr.id < 0 || (pr.hitdef.affectteam != 0 && |
@@ -1269,9 +1261,11 @@ func (p *Projectile) clsn(playerNo int) { | ||
1269 | 1261 | [...]float32{pr.pos[0] * pr.localscl, pr.pos[1] * pr.localscl}, pr.facing, |
1270 | 1262 | clsn2, [...]float32{p.clsnScale[0] * p.localscl, p.clsnScale[1] * p.localscl}, |
1271 | 1263 | [...]float32{p.pos[0] * p.localscl, p.pos[1] * p.localscl}, p.facing) { |
1272 | - opp, pp := &sys.projs[i][j], p.prioritypoint | |
1273 | - cancel(&p.prioritypoint, p.priority, &p.hits, opp.prioritypoint) | |
1274 | - cancel(&opp.prioritypoint, opp.priority, &opp.hits, pp) | |
1264 | + | |
1265 | + opp, pp := &sys.projs[i][j], p.priorityPoints | |
1266 | + cancel(&p.priorityPoints, &p.hits, opp.priorityPoints) | |
1267 | + cancel(&opp.priorityPoints, &opp.hits, pp) | |
1268 | + | |
1275 | 1269 | if p.hits < 0 { |
1276 | 1270 | break |
1277 | 1271 | } |
@@ -306,7 +306,9 @@ func (c *Compiler) operator(in *string) error { | ||
306 | 306 | if opp < 0 || ((!c.usiroOp || c.token[0] != '(') && |
307 | 307 | (c.token[0] < 'A' || c.token[0] > 'Z') && |
308 | 308 | (c.token[0] < 'a' || c.token[0] > 'z')) { |
309 | - return Error(c.maeOp + "が不正です") | |
309 | + return Error(c.maeOp + "が不正です" + | |
310 | + " / " + | |
311 | + c.maeOp + " is invalid") | |
310 | 312 | } |
311 | 313 | *in = c.token + " " + *in |
312 | 314 | c.token = c.maeOp |
@@ -326,7 +328,9 @@ func (c *Compiler) integer2(in *string) (int32, error) { | ||
326 | 328 | } |
327 | 329 | for _, c := range istr { |
328 | 330 | if c < '0' || c > '9' { |
329 | - return 0, Error(istr + "が整数でありません") | |
331 | + return 0, Error(istr + "が整数でありません" + | |
332 | + " / " + | |
333 | + istr + " is not an integer") | |
330 | 334 | } |
331 | 335 | } |
332 | 336 | i := Atoi(istr) |
@@ -384,7 +388,9 @@ func (c *Compiler) attr(text string, hitdef bool) (int32, error) { | ||
384 | 388 | (a < 'a' || a > 'z') { |
385 | 389 | return flg, nil |
386 | 390 | } |
387 | - return 0, Error(string(a) + "が無効な値です") | |
391 | + return 0, Error(string(a) + "が無効な値です" + | |
392 | + " / " + | |
393 | + string(a) + " is an invalid value") | |
388 | 394 | } |
389 | 395 | } |
390 | 396 | hitdefflg := flg |
@@ -431,7 +437,9 @@ func (c *Compiler) attr(text string, hitdef bool) (int32, error) { | ||
431 | 437 | } |
432 | 438 | return flg, nil |
433 | 439 | } |
434 | - return 0, Error(a + "が無効な値です") | |
440 | + return 0, Error(a + "が無効な値です" + | |
441 | + " / " + | |
442 | + a + " is an invalid value") | |
435 | 443 | } |
436 | 444 | if i == 0 { |
437 | 445 | hitdefflg = flg |
@@ -466,7 +474,9 @@ func (c *Compiler) trgAttr(in *string) (int32, error) { | ||
466 | 474 | case 'A', 'a': |
467 | 475 | flg |= int32(ST_A) |
468 | 476 | default: |
469 | - return 0, Error(att + "が不正な属性値です") | |
477 | + return 0, Error(att + "が不正な属性値です" + | |
478 | + " / " + | |
479 | + att + " is an invalid attribute value") | |
470 | 480 | } |
471 | 481 | } |
472 | 482 | for len(*in) > 0 && (*in)[0] == ',' { |
@@ -521,7 +531,9 @@ func (c *Compiler) trgAttr(in *string) (int32, error) { | ||
521 | 531 | } |
522 | 532 | func (c *Compiler) kakkohiraku(in *string) error { |
523 | 533 | if c.tokenizer(in) != "(" { |
524 | - return Error(c.token + "の次に'('がありません") | |
534 | + return Error(c.token + "の次に'('がありません" + | |
535 | + " / " + | |
536 | + "Missing '(' after " + c.token) | |
525 | 537 | } |
526 | 538 | c.token = c.tokenizer(in) |
527 | 539 | return nil |
@@ -529,7 +541,9 @@ func (c *Compiler) kakkohiraku(in *string) error { | ||
529 | 541 | func (c *Compiler) kakkotojiru() error { |
530 | 542 | c.usiroOp = true |
531 | 543 | if c.token != ")" { |
532 | - return Error(c.token + "の前に')'がありません") | |
544 | + return Error(c.token + "の前に')'がありません" + | |
545 | + " / " + | |
546 | + "There is no ')' before " + c.token) | |
533 | 547 | } |
534 | 548 | return nil |
535 | 549 | } |
@@ -549,7 +563,9 @@ func (c *Compiler) kyuushiki(in *string) (not bool, err error) { | ||
549 | 563 | continue |
550 | 564 | } |
551 | 565 | } |
552 | - return false, Error("'='か'!='がありません") | |
566 | + return false, Error("'='か'!='がありません" + | |
567 | + " / " + | |
568 | + "Missing '=' or '! ='") | |
553 | 569 | } |
554 | 570 | c.token = c.tokenizer(in) |
555 | 571 | return |
@@ -562,7 +578,9 @@ func (c *Compiler) intRange(in *string) (minop OpCode, maxop OpCode, | ||
562 | 578 | case "[": |
563 | 579 | minop = OC_ge |
564 | 580 | default: |
565 | - err = Error("'['か'('がありません") | |
581 | + err = Error("'['か'('がありません" + | |
582 | + " / " + | |
583 | + "Missing '[' or '('") | |
566 | 584 | return |
567 | 585 | } |
568 | 586 | var intf func(in *string) (int32, error) |
@@ -575,7 +593,9 @@ func (c *Compiler) intRange(in *string) (minop OpCode, maxop OpCode, | ||
575 | 593 | c.token = c.tokenizer(in) |
576 | 594 | } |
577 | 595 | if len(c.token) == 0 || c.token[0] < '0' || c.token[0] > '9' { |
578 | - return 0, Error("数字の読み込みエラーです") | |
596 | + return 0, Error("数字の読み込みエラーです" + | |
597 | + " / " + | |
598 | + "Error reading number") | |
579 | 599 | } |
580 | 600 | i := Atoi(c.token) |
581 | 601 | if minus { |
@@ -598,7 +618,9 @@ func (c *Compiler) intRange(in *string) (minop OpCode, maxop OpCode, | ||
598 | 618 | c.token = c.tokenizer(in) |
599 | 619 | } |
600 | 620 | if c.token != "," { |
601 | - err = Error("','がありません") | |
621 | + err = Error("','がありません" + | |
622 | + " / " + | |
623 | + "There is not ','") | |
602 | 624 | return |
603 | 625 | } |
604 | 626 | if max, err = intf(in); err != nil { |
@@ -618,7 +640,9 @@ func (c *Compiler) intRange(in *string) (minop OpCode, maxop OpCode, | ||
618 | 640 | case "]": |
619 | 641 | maxop = OC_le |
620 | 642 | default: |
621 | - err = Error("']'か')'がありません") | |
643 | + err = Error("']'か')'がありません" + | |
644 | + " / " + | |
645 | + "Missing ']' or ')'") | |
622 | 646 | return |
623 | 647 | } |
624 | 648 | c.token = c.tokenizer(in) |
@@ -666,7 +690,9 @@ func (c *Compiler) kyuushikiSuperDX(out *BytecodeExp, in *string, | ||
666 | 690 | case "=": |
667 | 691 | default: |
668 | 692 | if hissu && !comma { |
669 | - return Error("比較演算子がありません") | |
693 | + return Error("比較演算子がありません" + | |
694 | + " / " + | |
695 | + "No comparison operator") | |
670 | 696 | } |
671 | 697 | hikaku = false |
672 | 698 | } |
@@ -709,7 +735,9 @@ func (c *Compiler) kyuushikiSuperDX(out *BytecodeExp, in *string, | ||
709 | 735 | n, err := c.integer2(in) |
710 | 736 | if err != nil { |
711 | 737 | if hissu && !hikaku { |
712 | - return Error("比較演算子がありません") | |
738 | + return Error("比較演算子がありません"+ | |
739 | + " / " + | |
740 | + "No comparison operator") | |
713 | 741 | } |
714 | 742 | if hikaku { |
715 | 743 | return err |
@@ -728,7 +756,9 @@ func (c *Compiler) oneArg(out *BytecodeExp, in *string, | ||
728 | 756 | mae := c.token |
729 | 757 | if c.token = c.tokenizer(in); c.token != "(" { |
730 | 758 | if len(defval) == 0 || defval[0].IsNone() { |
731 | - return bvNone(), Error(mae + "の次に'('がありません") | |
759 | + return bvNone(), Error(mae + "の次に'('がありません" + | |
760 | + " / " + | |
761 | + "Missing '(' after " + mae) | |
732 | 762 | } |
733 | 763 | *in = c.token + " " + *in |
734 | 764 | bv = defval[0] |
@@ -853,7 +883,9 @@ func (c *Compiler) expValue(out *BytecodeExp, in *string, | ||
853 | 883 | text := func() error { |
854 | 884 | i := strings.Index(*in, "\"") |
855 | 885 | if c.token != "\"" || i < 0 { |
856 | - return Error("\"で囲まれていません") | |
886 | + return Error("\"で囲まれていません" + | |
887 | + " / " + | |
888 | + "Not enclosed in \"") | |
857 | 889 | } |
858 | 890 | c.token = (*in)[:i] |
859 | 891 | *in = (*in)[i+1:] |
@@ -901,7 +933,9 @@ func (c *Compiler) expValue(out *BytecodeExp, in *string, | ||
901 | 933 | var err error |
902 | 934 | switch c.token { |
903 | 935 | case "": |
904 | - return bvNone(), Error("空です") | |
936 | + return bvNone(), Error("空です" + | |
937 | + " / " + | |
938 | + "Empty") | |
905 | 939 | case "root", "parent", "helper", "target", "partner", |
906 | 940 | "enemy", "enemynear", "playerid": |
907 | 941 | switch c.token { |
@@ -944,7 +978,9 @@ func (c *Compiler) expValue(out *BytecodeExp, in *string, | ||
944 | 978 | case OC_partner, OC_enemy, OC_enemynear: |
945 | 979 | be1.appendValue(BytecodeInt(0)) |
946 | 980 | case OC_playerid: |
947 | - return bvNone(), Error("playeridの次に'('がありません") | |
981 | + return bvNone(), Error("playeridの次に'('がありません" + | |
982 | + " / " + | |
983 | + "There is no '(' after playerid") | |
948 | 984 | } |
949 | 985 | } |
950 | 986 | if rd { |
@@ -953,7 +989,9 @@ func (c *Compiler) expValue(out *BytecodeExp, in *string, | ||
953 | 989 | out.append(be1...) |
954 | 990 | } |
955 | 991 | if c.token != "," { |
956 | - return bvNone(), Error(",がありません") | |
992 | + return bvNone(), Error(",がありません" + | |
993 | + " / " + | |
994 | + "Missing ','" ) | |
957 | 995 | } |
958 | 996 | c.token = c.tokenizer(in) |
959 | 997 | if bv2, err = c.expValue(&be2, in, true); err != nil { |
@@ -969,7 +1007,9 @@ func (c *Compiler) expValue(out *BytecodeExp, in *string, | ||
969 | 1007 | c.token += c.tokenizer(in) |
970 | 1008 | bv = c.number(c.token) |
971 | 1009 | if bv.IsNone() { |
972 | - return bvNone(), Error(c.token + "が不正です") | |
1010 | + return bvNone(), Error(c.token + "が不正です" + | |
1011 | + " / " + | |
1012 | + c.token + " is invalid") | |
973 | 1013 | } |
974 | 1014 | } else { |
975 | 1015 | c.token = c.tokenizer(in) |
@@ -2111,11 +2151,11 @@ func (c *Compiler) expValue(out *BytecodeExp, in *string, | ||
2111 | 2151 | } else if len(c.token) >= 2 && c.token[0] == '$' && c.token != "$_" { |
2112 | 2152 | vi, ok := c.vars[c.token[1:]] |
2113 | 2153 | if !ok { |
2114 | - return bvNone(), Error(c.token + "は定義されていません") | |
2154 | + return bvNone(), Error(c.token + "は定義されていません" + " / " + c.token + "Is not defined") | |
2115 | 2155 | } |
2116 | 2156 | out.append(OC_localvar, OpCode(vi)) |
2117 | 2157 | } else { |
2118 | - return bvNone(), Error(c.token + "が不正です") | |
2158 | + return bvNone(), Error(c.token + "が不正です" + " / " + c.token + "It is illegal") | |
2119 | 2159 | } |
2120 | 2160 | } |
2121 | 2161 | c.token = c.tokenizer(in) |
@@ -628,11 +628,17 @@ func JoystickState(joy, button int) bool { | ||
628 | 628 | if (button == 8 || button == 10) && glfw.GetJoystickName(joystick[joy]) == "Xbox 360 Controller" { //Xbox360コントローラーのLRトリガー判定 |
629 | 629 | return axes[button/2] > 0 |
630 | 630 | } |
631 | + | |
632 | + // Ignore trigger axis on PS4 (We already have buttons) | |
633 | + if (button >= 6 && button <= 9) && glfw.GetJoystickName(joystick[joy]) == "Wireless Controller" { | |
634 | + return false | |
635 | + } | |
636 | + | |
631 | 637 | switch button & 1 { |
632 | - case 0: | |
633 | - return axes[button/2] < -0.2 | |
634 | - case 1: | |
635 | - return axes[button/2] > 0.2 | |
638 | + case 0: | |
639 | + return axes[button/2] < -0.2 | |
640 | + case 1: | |
641 | + return axes[button/2] > 0.2 | |
636 | 642 | } |
637 | 643 | } |
638 | 644 | if len(btns) <= button { |
@@ -1227,10 +1227,13 @@ func systemScriptInit(l *lua.LState) { | ||
1227 | 1227 | s = strconv.Itoa(-i*2 - 1) |
1228 | 1228 | } |
1229 | 1229 | } else { |
1230 | - if axes[i] < -0.2 { | |
1231 | - s = strconv.Itoa(-i*2 - 1) | |
1232 | - } else if axes[i] > 0.2 { | |
1233 | - s = strconv.Itoa(-i*2 - 2) | |
1230 | + // PS4 Controller support | |
1231 | + if glfw.GetJoystickName(joystick[j]) != "Wireless Controller" || !(i == 3 || i == 4) { | |
1232 | + if axes[i] < -0.2 { | |
1233 | + s = strconv.Itoa(-i*2 - 1) | |
1234 | + } else if axes[i] > 0.2 { | |
1235 | + s = strconv.Itoa(-i*2 - 2) | |
1236 | + } | |
1234 | 1237 | } |
1235 | 1238 | } |
1236 | 1239 | } |
@@ -3,6 +3,7 @@ package main | ||
3 | 3 | import ( |
4 | 4 | "encoding/binary" |
5 | 5 | "fmt" |
6 | + "io" | |
6 | 7 | "math" |
7 | 8 | "os" |
8 | 9 | "path/filepath" |
@@ -15,6 +16,7 @@ import ( | ||
15 | 16 | "github.com/faiface/beep/mp3" |
16 | 17 | "github.com/faiface/beep/speaker" |
17 | 18 | "github.com/faiface/beep/vorbis" |
19 | + "github.com/faiface/beep/wav" | |
18 | 20 | ) |
19 | 21 | |
20 | 22 | const ( |
@@ -237,17 +239,21 @@ func (n *NormalizerLR) process(bai float64, sam *float32) float64 { | ||
237 | 239 | |
238 | 240 | type Bgm struct { |
239 | 241 | filename string |
242 | + bgmVolume int | |
240 | 243 | bgmLoopStart int |
241 | 244 | bgmLoopEnd int |
242 | 245 | defaultFilename string |
243 | 246 | defaultBgmVolume int |
244 | 247 | defaultbgmLoopStart int |
245 | 248 | defaultbgmLoopEnd int |
249 | + loop int | |
246 | 250 | sampleRate beep.SampleRate |
247 | 251 | streamer beep.StreamSeekCloser |
248 | 252 | ctrl *beep.Ctrl |
249 | 253 | resampler *beep.Resampler |
250 | 254 | volume *effects.Volume |
255 | + format string | |
256 | + tempfile io.ReadCloser | |
251 | 257 | } |
252 | 258 | |
253 | 259 | func newBgm() *Bgm { |
@@ -266,6 +272,10 @@ func (bgm *Bgm) IsFLAC() bool { | ||
266 | 272 | return bgm.IsFormat(".flac") |
267 | 273 | } |
268 | 274 | |
275 | +func (bgm *Bgm) IsWAVE() bool { | |
276 | + return bgm.IsFormat(".wav") | |
277 | +} | |
278 | + | |
269 | 279 | func (bgm *Bgm) IsFormat(extension string) bool { |
270 | 280 | return filepath.Ext(bgm.filename) == extension |
271 | 281 | } |
@@ -275,6 +285,8 @@ func (bgm *Bgm) Open(filename string, isDefaultBGM bool, loop, bgmVolume, bgmLoo | ||
275 | 285 | return |
276 | 286 | } |
277 | 287 | bgm.filename = filename |
288 | + bgm.loop = loop | |
289 | + bgm.bgmVolume = bgmVolume | |
278 | 290 | bgm.bgmLoopStart = bgmLoopStart |
279 | 291 | bgm.bgmLoopEnd = bgmLoopEnd |
280 | 292 | if isDefaultBGM { |
@@ -290,7 +302,9 @@ func (bgm *Bgm) Open(filename string, isDefaultBGM bool, loop, bgmVolume, bgmLoo | ||
290 | 302 | } else if bgm.IsMp3() { |
291 | 303 | bgm.ReadMp3(loop, bgmVolume) |
292 | 304 | } else if bgm.IsFLAC() { |
293 | - bgm.ReadFLAC(loop, bgmVolume) | |
305 | + bgm.ConvertFLAC(loop, bgmVolume) | |
306 | + } else if bgm.IsWAVE() { | |
307 | + bgm.ReadWav(loop, bgmVolume) | |
294 | 308 | } |
295 | 309 | |
296 | 310 | } |
@@ -299,6 +313,7 @@ func (bgm *Bgm) ReadMp3(loop int, bgmVolume int) { | ||
299 | 313 | f, _ := os.Open(bgm.filename) |
300 | 314 | s, format, err := mp3.Decode(f) |
301 | 315 | bgm.streamer = s |
316 | + bgm.format = "mp3" | |
302 | 317 | if err != nil { |
303 | 318 | return |
304 | 319 | } |
@@ -309,6 +324,42 @@ func (bgm *Bgm) ReadFLAC(loop int, bgmVolume int) { | ||
309 | 324 | f, _ := os.Open(bgm.filename) |
310 | 325 | s, format, err := flac.Decode(f) |
311 | 326 | bgm.streamer = s |
327 | + bgm.format = "flac" | |
328 | + | |
329 | + if err != nil { | |
330 | + return | |
331 | + } | |
332 | + bgm.ReadFormat(format, loop, bgmVolume) | |
333 | +} | |
334 | + | |
335 | +// SCREW THE FLAC.SEEK FUNCTION, IT DOES NOT WORK SO WE ARE GOING TO CONVERT THIS TO WAV | |
336 | +func (bgm *Bgm) ConvertFLAC(loop int, bgmVolume int) { | |
337 | + // We open the flac | |
338 | + f1, _ := os.Open(bgm.filename) | |
339 | + // And create a temp one | |
340 | + f2, _ := os.Create("save/tempaudio.wav") | |
341 | + | |
342 | + // Open decode and convert | |
343 | + s, format, err := flac.Decode(f1) | |
344 | + wav.Encode(f2, s, format) | |
345 | + | |
346 | + bgm.filename = "save/tempaudio.wav" | |
347 | + //bgm.tempfile = f2 | |
348 | + bgm.format = "flac" | |
349 | + | |
350 | + s.Close() | |
351 | + | |
352 | + if err != nil { | |
353 | + return | |
354 | + } | |
355 | + | |
356 | + sys.FLAC_FrameWait = 120 | |
357 | +} | |
358 | + | |
359 | +func (bgm *Bgm) PlayMemAudio(loop int, bgmVolume int) { | |
360 | + f, _ := os.Open(bgm.filename) | |
361 | + s, format, err := wav.Decode(f) | |
362 | + bgm.streamer = s | |
312 | 363 | if err != nil { |
313 | 364 | return |
314 | 365 | } |
@@ -319,6 +370,18 @@ func (bgm *Bgm) ReadVorbis(loop int, bgmVolume int) { | ||
319 | 370 | f, _ := os.Open(bgm.filename) |
320 | 371 | s, format, err := vorbis.Decode(f) |
321 | 372 | bgm.streamer = s |
373 | + bgm.format = "ogg" | |
374 | + if err != nil { | |
375 | + return | |
376 | + } | |
377 | + bgm.ReadFormat(format, loop, bgmVolume) | |
378 | +} | |
379 | + | |
380 | +func (bgm *Bgm) ReadWav(loop int, bgmVolume int) { | |
381 | + f, _ := os.Open(bgm.filename) | |
382 | + s, format, err := wav.Decode(f) | |
383 | + bgm.streamer = s | |
384 | + bgm.format = "wav" | |
322 | 385 | if err != nil { |
323 | 386 | return |
324 | 387 | } |
@@ -64,6 +64,7 @@ var sys = System{ | ||
64 | 64 | keyInput: glfw.KeyUnknown, |
65 | 65 | keyString: "", |
66 | 66 | comboExtraFrameWindow: 1, |
67 | + FLAC_FrameWait: -1, | |
67 | 68 | // Localcoord sceenpack |
68 | 69 | luaSpriteScale: 1, |
69 | 70 | luaSmallPortraitScale: 1, |
@@ -248,6 +249,7 @@ type System struct { | ||
248 | 249 | wavVolume int |
249 | 250 | bgmVolume int |
250 | 251 | AudioDucking bool |
252 | + FLAC_FrameWait int | |
251 | 253 | // Localcoord sceenpack |
252 | 254 | luaSpriteScale float64 |
253 | 255 | luaSmallPortraitScale float32 |
@@ -433,7 +435,7 @@ func (s *System) soundWrite() { | ||
433 | 435 | processed = true |
434 | 436 | } |
435 | 437 | if !s.nomusic { |
436 | - if s.bgm.ctrl != nil { | |
438 | + if s.bgm.ctrl != nil && s.bgm.streamer != nil { | |
437 | 439 | s.bgm.ctrl.Paused = false |
438 | 440 | if s.bgm.bgmLoopEnd > 0 && s.bgm.streamer.Position() >= s.bgm.bgmLoopEnd { |
439 | 441 | s.bgm.streamer.Seek(s.bgm.bgmLoopStart) |
@@ -445,6 +447,12 @@ func (s *System) soundWrite() { | ||
445 | 447 | } |
446 | 448 | } |
447 | 449 | |
450 | + if s.FLAC_FrameWait >= 0 { | |
451 | + if s.FLAC_FrameWait == 0 { | |
452 | + s.bgm.PlayMemAudio(s.bgm.loop, s.bgm.bgmVolume) | |
453 | + } | |
454 | + s.FLAC_FrameWait-- | |
455 | + } | |
448 | 456 | } |
449 | 457 | src.Delete() |
450 | 458 | openal.NullContext.Activate() |
@@ -1379,7 +1387,20 @@ func (s *System) fight() (reload bool) { | ||
1379 | 1387 | } |
1380 | 1388 | put(&y, s.stage.def) |
1381 | 1389 | if s.debugWC != nil { |
1382 | - put(&y, fmt.Sprintf("<P%v:%v>", s.debugWC.playerNo+1, s.debugWC.name)) | |
1390 | + //put(&y, fmt.Sprintf("<P%v:%v>", s.debugWC.playerNo+1, s.debugWC.name)) | |
1391 | + if s.bgm.streamer != nil { | |
1392 | + put(&y, fmt.Sprintf("BgmPos: %v", s.bgm.streamer.Position())) | |
1393 | + put(&y, fmt.Sprintf("BgmLen: %v", s.bgm.streamer.Len())) | |
1394 | + if s.nomusic == false { | |
1395 | + put(&y, fmt.Sprintf("BgmPlayback: enabled")) | |
1396 | + } else { | |
1397 | + put(&y, fmt.Sprintf("BgmPlayback: disabled")) | |
1398 | + } | |
1399 | + put(&y, fmt.Sprintf("BgmLoopEnd: %v", s.bgm.bgmLoopEnd)) | |
1400 | + put(&y, fmt.Sprintf("BgmLoopStart: %v", s.bgm.bgmLoopStart)) | |
1401 | + } else { | |
1402 | + put(&y, fmt.Sprintf("BgmPlayback: disabled")) | |
1403 | + } | |
1383 | 1404 | } |
1384 | 1405 | for i, p := range s.chars { |
1385 | 1406 | if len(p) > 0 { |