Ruby Journey version Numworks !!! (devlogs sur le vrai jeu: youtube.com/@aizeir)
from math import * from random import * from kandinsky import * from ion import * from time import sleep, monotonic ## ENGINE W,H = 320,222 SIZE, WIN = (W,H), (0,0,W,H) FONTW, FONTH = 10,18 # Colors GRAY3 = (51, 51, 51) # 333333 BLACK = (25, 31, 34) # 191f22 GRAY2 = (89, 82, 70) # 595246 GRAY1 = (128, 118, 101) # 807665 GRAY0 = (187, 176, 148) # bbb094 GREEN4 = (47, 68, 67) # 2f4443 GREEN3 = (59, 94, 88) # 3b5e58 GREEN2 = (90, 140, 108) # 5a8c6c GREEN1 = (139, 180, 141) # 8bb48d GREEN0 = (192, 208, 165) # c0d0a5 WHITE = (247, 239, 199) # f7efc7 BLUE1 = (161, 205, 176) BLUE2 = (112, 147, 149) # 709395 BLUE3 = (74, 120, 123) # 4a787b PINK3 = (56, 49, 64) # 383140 PINK2 = (115, 77, 92) # 734d5c PINK1 = (167, 103, 114) # a76772 PINK0 = (204, 134, 125) # cc867d ORANGE0 = (224, 186, 139) # e0ba8b ORANGE1 = (195, 130, 82) # c38252 ORANGE2 = (161, 86, 60) # a1563c ORANGE3 = (111, 52, 45) # 6f342d ORANGE4 = (68, 39, 31) # 44271f COLORS = [GRAY3, BLACK, GRAY2, GRAY1, GRAY0, GREEN4, GREEN3, GREEN2, GREEN1, GREEN0, WHITE, BLUE1, BLUE2, BLUE3, PINK3, PINK2, PINK1, PINK0, ORANGE0, ORANGE1, ORANGE2, ORANGE3, ORANGE4] # Utils def clamp(m,x,M): return max(m,min(x,M)) def proba(n): return randint(1,n)==1 def ints(list): return tuple(int(x) for x in list) def center_pos(rect): return rect[0]+rect[2]//2, rect[1]+rect[3]//2 # - collision def collide_x(r1,r2): return r1[0] < r2[0]+r2[2] and r2[0] < r1[0]+r1[2] def collide_y(r1,r2): return r1[1] < r2[1]+r2[3] and r2[1] < r1[1]+r1[3] def collide (r1,r2): return collide_x(r1,r2) and collide_y(r1,r2) # - rect def bottom(rect): return rect[1]+rect[3] def right(rect): return rect[0]+rect[2] def add(r1,r2): res = [] for i in range(max(len(r1),len(r2))): x = r1[i] if i < len(r1) else 0 y = r2[i] if i < len(r2) else 0 res.append(x+y) return res # - drawing def draw_rect(rect, color): fill_rect(int(rect[0]),int(rect[1]),int(rect[2]),int(rect[3]),color) def draw_rect_mult(x,y,w,h, color): fill_rect(int(x),int(y),int(w),int(h),color) def fill(color=WHITE): draw_rect(WIN, color) def draw_rects(img,color=BLACK, X=0,Y=0): """( (x,y,w,h[,color]), ... )""" for r in img: draw_rect_mult(X+r[0],Y+r[1], r[2], r[3], (r[4] if len(r) > 4 else color)) def draw_text(text, x, y, side="topleft", color=BLACK, background=WHITE): if "right" in side: x -= len(text)*FONTW elif not "left" in side: x -= len(text)*FONTW/2 if "bottom" in side: y -= FONTH elif not "top" in side: y -= FONTH/2 draw_string(text, int(round(x)),int(round(y)), color, background) # - time (time: ne pas utiliser en dehors d'engine) _time,timers = 0,{} def every(dt): if dt not in timers: timers[dt] = _time return (_time - timers[dt]) >= dt def timer(t, dura): return (monotonic() - t) >= dura # - update just_pressed,_pressed = {},{} def update(keys=[KEY_OK]): """ keys: touches inscrites dans just_pressed. ATTENTION: ne JAMAIS utiliser just_pressed dans un "every" """ global _time for dt in timers: if _time-timers[dt] >= dt: timers[dt] = _time _time = monotonic() for key in keys: kd = keydown(key) just_pressed[key] = kd and not _pressed.get(key) _pressed[key] = kd return True ## IMAGES map=""" -1,5,-1,-1,9,-1,-1,-1,-1,-1,-1,11,9,-1,-1,8,9,-1,9,-1,-1,11,-1,9,-1,-1,-1,-1,-1,9 -1,-1,-1,11,-1,-1,11,-1,4,-1,-1,4,-1,-1,-1,-1,-1,4,11,-1,-1,-1,9,-1,14,-1,-1,11,5,-1 9,-1,-1,-1,-1,5,-1,-1,-1,-1,-1,-1,-1,13,-1,9,-1,-1,11,-1,-1,5,-1,-1,-1,-1,-1,4,-1,9 -1,-1,9,-1,-1,-1,-1,9,-1,-1,-1,-1,-1,-1,-1,-1,-1,4,-1,-1,-1,-1,-1,-1,8,-1,-1,-1,9,-1 4,-1,-1,-1,13,-1,-1,8,10,-1,-1,-1,5,10,-1,-1,-1,-1,-1,-1,-1,-1,4,-1,-1,-1,-1,8,-1,-1 -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1 -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1 -1,4,-1,-1,4,-1,-1,-1,5,-1,-1,-1,-1,-1,6,-1,-1,10,11,-1,-1,4,-1,-1,-1,-1,-1,14,-1,8 4,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,0,-1,-1,-1,12,-1,-1,-1,-1,-1,-1,-1,13,-1,-1,-1,-1,-1,5 -1,-1,-1,-1,-1,9,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,11,-1,-1,-1,-1,-1,-1,-1,11,-1,-1,9,9 -1,9,10,-1,-1,-1,9,4,-1,-1,-1,5,-1,-1,-1,9,-1,-1,-1,-1,-1,5,-1,-1,-1,-1,-1,10,9,9 -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1 -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1 -1,4,-1,-1,-1,-1,-1,-1,14,-1,-1,-1,-1,5,-1,-1,-1,-1,4,-1,-1,4,-1,10,-1,4,-1,-1,-1,-1 11,-1,-1,8,9,-1,5,-1,-1,-1,-1,-1,-1,9,-1,7,11,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,13,-1,-1 -1,-1,-1,-1,-1,-1,-1,-1,4,-1,-1,-1,10,-1,-1,-1,10,8,-1,-1,-1,-1,-1,9,-1,-1,-1,-1,9,-1 -1,4,-1,-1,13,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,8,-1,11,11 -1,-1,9,-1,-1,9,-1,4,-1,-1,-1,-1,4,-1,9,-1,-1,9,11,-1,-1,-1,5,-1,-1,9,-1,-1,11,11 """ imgs = ['4"5"6"7"8"9":";"<"="D"E$F$G#H#I#J#K#L#M"T"U$V#W#X#Y#Z#[#\\#]"d"e#f#g4h4i4j4k#l"m"t"u#v4!K"9#K$K%9&9.9/K0K1K293K4K5969>9?K@KAKBKCKDKEKF9N9OKPKQKRKSKTKUKV9^9_9`9a9b9c9d9e9f9o9pMqMrMsMtMu9)P*c+c,c-c.c/P9P:P;P<P=P>P?PIPJ^K^LPMPN^OPYPZP[P]P^P_P', '4"5"6"7"8"9":";"<"="D"E#F#G#H#I#J#K$L$M"T"U#V#W#X#Y#Z#[#\\$]"d"e"f#g4h4i4j4k#l#m"u"v"!K"K#9$K%K&:\'9/9091K2K394K5K6K79?9@KAKBKCKDKEKFKG9O9PKQKRKSKTKUKVKW9_9`9a9b9c9d9e9f9g9p9qMrMsMtMuMv9*P+c,c-c.c/c0P:P;P<P=P>P?P@PJPK^LPMPN^O^PPZP[P\\P^P_P`P', '5"6"7"8"9":";"D"E#F#G#H#I#J#K#L"T"U#V#W#X#Y#Z#[#\\"d"e#f4g4h4i4j4k#l"t"u4v"!K"K#K$9%K&9.9/K091K2K3K495K69>9?K@KAKBKCKDKEKF9N9OKPKQKRKSKTKUKV9^9_9`9a9b9c9d9e9f9o9pMqMrMsMtMu9)P*c+c,c-c.c/P9P:P;P<P=P>P?PIPJ^K^LPM^N^OPYPZP[P]P^P_P', '6"7"8"9":"E"F#G#H#I#J#K"T"U#V#W#X#Y#Z#[#\\"d"e#f#g#h#i#j#k#l"t"u!v!!8"8#8$8%8&9.9/K0K1K2K3K4K5K69>9?K@KAKBKCKDKEKF9N9OKPKQKRKSKTKUKV9^9_9`9a9b9c9d9e9f9o9pMqMrMsMtMu9)P*c+c,c-c.c/P9P:P;P<P=P>P?PIPJ^K^LPM^N^OPYPZP[P]P^P_P', '5"6"7"8"9":";"<"D"E&F&G&H&I&J&K&L&M"S"T&U\'V\'W\'X\'Y\'Z\'[\'\\\']&^"b"c&d\'e(f(g(h(i(j(k(l(m\'n&o"q"r&s\'t(u(v(!?"?#?$?%?&?\'?(>)=*9+9,=->.?/?0?1?2?3?4?5?6?7?8>9=:9;9<==>>>??@?A?B?C?D?E?F?G>H>I=J9K9L=M=N>O>P>Q>R>S>T>U>V>W>X=Y=Z9[9\\9]=^=_=`>a>b>c>d>e>f=g=h=i9j9l9m9n=o=p=q=r=s=t=u=v=!T"P#P\'P(P)P*P+P,P-P.P/P0P1P2P:P;e<d=d>e?PIPJPKeLdMdNeOPPPYPZe[d\\d]d^d_e`PjPkPlPmPnPoP', '5"6"7"8"9":";"<"D"E&F&G&H&I&J&K&L&M"S"T&U\'V\'W\'X\'Y\'Z\'[\'\\\']&^"b"c&d\'e(f(g(h(i(j(k(l(m\'n&o"q"r&s\'t(u(v)!@"@#@$@%@&?\'?(>)=*9+9,=->.>/?0?1@2@3@4@5?6?7>8>9=:9;9<==>>>?>@>A?B?C?D?E>F>G>H>I=J9K9L=M=N=O>P>Q>R>S>T>U>V>W=X=Y=Z9\\9]9^=_=`=a=b=c=d=e=f=g=h9i9m9n9o=p=q=r=s=t=u=v=!P"P(P)P*P+P,P-P.P/P0P1P:P;e<d=d>e?PIPJPKeLdMdNeOPPPYPZe[d\\d]d^d_e`PjPkPlPmPnPoP', '%"&"\'"(")"*"+"4"5,6,7,8,9,:,;,<"D"E(F,G,H,I,J,K(L"T"U*V(W(X(Y(Z([*\\"d"e"f*g*h*i*j*k"l"t"u4v"!9"9#9$9%K&9.9/J091K2K3K495J69>9?J@9AJBJCJD9EJF9N9OJPJQJRJSJTJUJV9^9_9`9a9b9c9d9e9f9o9p?q@r?s?t@u9)P*W+V,V-W.V/P9P:P;P<P=P>P?PIPJUKULPMUNUOPYPZP[P]P^P_P', '4"5"6"7"8"9":";"<"D"E$F$G$H$I$J$K$L"T"U$V$W4X4Y4Z$[$\\"d"e$f$g4h4i4j$k$l"t"u#v5!L"L#L$L%:&9.9/L091L2L3L495L69>9?L@9ALBLCLD9ELF9N9OLPLQLRLSLTLULV9^9_9`9a9b9c9d9e9f9o9pHqGrHsGtHu9)P*^+^,^-^.^/P9P:P;P<P=P>P?PIPJ]K]LPM]N]OPYPZP[P]P^P_P', 'G"H"I"J"K"U"V"W&X\'Y\'Z&[&\\"d"e&f\'g\'h(i(j\'k&l"m"s"t"u\'v(!?"?#?$?%>&=\'9-9.=/>0?1?2?3?4?5?6>7989=9>>??@?A?B?C?D?E>F=G=H9M9N=O>P?Q?R?S?T?U?V>W=X9]9^=_>`>a>b?c?d>e>f=g9h9m9n9o=p=q>r>s>t=u=v=!P"P(P)P*P+T,T-T.P/T0P1P9P:P;P<P=P>P?P@PJPKPLPMPNPOP', '6"7"8"9":";"E"F#G#H#I#J#K#L"T"U#V#W#X#Y#Z#[#\\#]"d"e#f#g#h#i#j#k#l#m"s"t"u!v#!:":#:$:%:&8\'9(9,9-8.9/9081:2:3:4:5869798899<9=:>8?9@8A8B8C8D8E8F9G8H:I9L9M:N:O:P8Q8R8S8T8U8V:W:X:Y9\\9]8^:_:`:a:b:c:d:e:f:g:h8i9l9m9n8o8p:q:r:s:t:u:v8!O"P#P&P\'P(P)O*O+O,O-O.O/O0O1P2P3P7P8P9P:O;O<O=O>O?O@PAPBPHPIPJPKPLPMPNPOPPPQPZP[P\\P]P^P_P', '87G7H6I7W7X6Y7f7g6h5i6j7v7!L"K#L$N0N1K2J3K4NA9BMC9Q9RNS9a9bNc9q9rNs9+P,e-P;P<e=PKPLeMP', '\'&(&)&*"6&7(8(9(:\';"E&F(G(H(I(J\'K6L"U&V(W(X\'Y\'Z6[6\\"d&e&f(g\'h6i6j6k6l"m"s&t\'u&v\'!?"M#M$M%M&9\'N(9,=-?.>/=0?1?2>3>4M5M697N8M99<==?>>?=@?A>B=C=D9EMF9GNHMI9L=M?N>O=P>Q>R=S=TNU9V9WNXMY9\\=]?^>_=`>a=bNcNdNeNf9gNhMi9l=m?n>o=p=qNrNsNtNu9v9!e"d#P&T\'V(T)U*U+P,P-P.P/e0e1P2d3P6T7T8U9U:U;U<P=P>e?e@eAeBPCPFTGUHUIUJUKULPMPNeOePeQeReSPWTXUYUZU[T]P^P_e`eaebPhTiTjTnPoPpPqP', 'E"F"H"I5K"L"T"U6V6W"X5Y5Z"[6\\6]"c"d7e6f6g5h5i5j5k6l6m7n"s"t7u6v6!L"K#K$L%M&M\'N(9-9.8/M0L1L2K3K4L5L6M7889=9>N?M@LAKBKCKDKELFMGNH9M9NNOMPLQKRJSJTKULVMWNX9]9^8_M`MaKbJcJdKeMfMg8h9m9nNoMpMqNrMsMtNuMvM!e"P\'P(e)d*d+e,d-d.e/d0d1e2P7P8O9d:d;O<d=d>O?d@dAOBPHPIeJeKPLeMeNPOePeQPYPZP\\P]P_P`P', 'I"J"M"X"Y5Z5["\\"]5^"h"i6j6k5l5m6n"q"r"s"t""9#L$L%M&M\'M(9)9+9,J-J.K/909293L4M5B6M7M8B9M:9;9<J=K>L?K@9A9BMCLDLEMFMGMHMILJ9K9LKMLNKOMP9QLRLSMTLULVLWLXLY9\\9]K^M_N`LaLbMcNdMeMfMgMh9m9n9oMpLqMrMsMtNuNv9!P(P)d*d+e,e-d.d/P0P8P9d:P;P<P=d>P?e@PHPIPKPLPMPNPOP', 'D"G"H"S"T5U"V"W5X5Y"c"d6e5f5g6h6i"r"s"t6u6v6!L"L#9\'9(9)9*9+9,M-B.M/M0B1M2L3959697K8J9J:9;9<L=M>M?M@MALBLCMD9E9FKGLHKIJJ9L9MLNLOLPLQLRMSLTLU9VMWKXLYKZ9]9^M_M`MaMbNcMdLeLfNgMhKi9n9o9pNqNrMsMtMuLvM!P"P)P*P+d,d-e.e/d0d1P9P:e;P<d=P>P?P@dAPJPKPLPMPNPPPQP', "T'X'e'g'u'!>?UPU`U", "M'U5^'d5e3f5n't'u5v'/>k>!c&U)U0c1a2c6U8U@UAcBUHUQU", "e't'.>e@fAgAt@u@vA.W/W0U1U?U@U", "<)=*>*K)L)M*[)\\)]'^'d'l'm't'r@sAtA&X'X(W+W,W-X7X8W9W;W<W=U>UFUGUHWIWLUMUWUXU"] items = ['Y7Z7[7\\7e7f7g7h7i3j3k+l+m7n7r7s7t7u3v3!B"B#B$B%B&B\'B(B)N,N-J.B/B0B1B2B3B4B5B6B7K8K9N<N=J>J?J@BABBBCBDBEKFKGKHKINLNMJNJOJPJQJRBSKTKUKVKWKXKYN\\N]J^J_J`JaJbBcKdKeKfKgKhKiNlNmJnJoJpJqJrBsKtKuKvK!b"e#e\'e(e)a*a+a,Y-b.b/b0e1e9e:e;a<Y=b>e?eKeLeMe', 'U/V/W/X/Y/Z/[/\\/d/e1f1g/h2i2j/k1l1m/s/t1u1v/!I"I#I$I%F&H\'H(F,F-H.H/F0I1I2I3I4I5I6F7H8H9F<F=F>F?F@FAFBFCFDFEFFFGFHFIFMFNGOGPFQHRHSHTHUFVGWGXF^F_G`FaFbHcHdFeGfGgFoFpGqFrHsHtFuGvF*]+^,]-].^/];]<]=]>]L]M]', 'W"X"Y"Z"f"g%h%i%j%k"l"u"v%!;";#;$;%:&:\'9.9/<0;1;2;3;4;5:6:79>9?<@;A;B;C;D:E:F:G8H9M9N<O;P;Q;R;S:T:U:V8W8X9]9^<_;`;a:b:c:d:e8f8g8h9m9n;o:p:q:r:s:t8u8v8!O"P\'P(R)Q*Q+Q,O-O.O/O0O1P8P9O:O;O<O=O>O?P@PIPJPKPLPMPNP', 'V!W!X"e!f+g%h$i"j"k"u!v%!;":#M$N%N&9/80<1;2:3M4N5N69?8@<A;B:CMDNENF9O8P<Q;R:SMTNUNV9_8`Ba<b;c9dNe9p8q8r9s9tMu9-P.c/P=P>c?PMPNdOP]P^e_PmPnPoP', 'X!g!h6i"u!v!!B"<#;$9%9.8/B0B1<2;3;4:5:69=8>B?<@9A;B:C:D9E:F:G9L8M<N9O9P9Q9RNS9T9U9V9W:X9\\9]9a9bMc9g9h9q9rLs9+P,c-P;P<c=PKPLdMP[P\\e]PkPlPmP', 'X!Y!Z"g!h+i%j"v!!B"<#;$9081<2;39@8A<B;C9P8Q;RNS9`9a9bMc9q9rLs9+P,d-P;P<e=PJPKQLRMQNPZP[P\\Q]P^PkPlPmP', 'V/W/X/Y/Z/[/f/g2h2i1j1k/v/!I"I#H$H%F0F1I2I3H4H5F@FAIBHCHDHEFPFQIRHSHTGUF`FaIbHcHdGeFpFqHrHsHtGuF*]+_,_-^.^/]:];_<^=^>^?]J]K_L^M^N^O]Z][]\\]]]^]_]', 'Z#[#\\#g#h#i#j%k%l%m#n#t#u#v#!<"<#<$<%<&<\'<(<):-:.</<0<1<2<3<4<5<6<7:8:98=:>;?;@<A<B<C<D<E:F:G:H:I8M:N;O;P;Q;R<S:T:U:V:W:X:Y8]:^;_;`;a;b<c:d:e:f:g:h8n:o;p;q;r<s:t:u:v8!O)Q*Q+R,S-Q.O/O;Q<Q=O'] itemnames = ["gold","ruby","stone","axe","pickaxe","lance","wood","iron"] pnjs = {6:"explorer",7:"blacksmith"} talks = { 6: ["hello how are you ?","YOU: i'm good.","you still think of that ruby ?","YOU: yes, or i wouldn't stay.", "good determination.", "but i think you'll not get it.","YOU: shut up."], 7: ["hello how is it ?","YOU: i'm fine.","can i tell you a joke ?","how to make a firefly happy?","YOU: what?!","cut its tail,it'll be delighted", "YOU: ...", "YOU: (dies of cringe)"], } trades = { 6: [(0,1,6,40),(6,4,2,1),(7,3,5,1),(0,2,1,1)], 7: [(2,4,7,1),(7,2,3,1),(7,2,4,1),(7,4,0,1)], } quests = { 6: [["10 wood to lit campfire", (6,10), "thank you ! (+2 stone)", (2,2)], ["give 1 iron, get a surprise", (7,1), "haha scammed you ! (+1 stone)", (2,1)]], 7: [["need 4 more rocks...", (2,4), "nice ! (+16 wood)", (6,16)], ["help need 2 iron now !", (7,2), "didn't used ur rocks (+4 rocks)", (2,4)]], } TALK_PNJ = "1:trade | 2:quest | 3:talk" QUEST_NO_NEED = "i don't need anything." FRIENDSHIP = "new trade unlocked !" tools = {4:(3,6,2),5:(3,6,2),8:(3,6,1),9:(4,2,1),11:(3,6,3),13:(5,None,0),14:(5,None,0)} tools_items = (3,4,5) ## JEU TS = 32 scale = TS//16 DSP_W, DSP_H = W//TS, H//TS ECART = H-DSP_H*TS PLR_SPAWN = 5, 1 MOVE_COOLDOWN = 0.1 FLOOR = GREEN2 FLOORED = [15,16,17,18] # Map map = map.strip().split("\n") MAPW, MAPH = len(map[0].split(",")), len(map) in_bounds = lambda x,y: 0 <= x < MAPW and 0 <= y < MAPH def create_world(): world = [0 for _ in range(MAPW*MAPH)] plr_pos = None for y in range(MAPH): row = map[y].split(",") for x in range(MAPW): tile = int(row[x]) if tile == 0: plr_pos = (x,y) tile = -1 world[y*MAPW+x] = tile if tile != -1 else choice(FLOORED) return world, plr_pos[0], plr_pos[1] # Dessiner monde def draw_tile(tile_x, tile_y, offset, color): fill_rect((tile_x-offset[0])*TS, (tile_y-offset[1])*TS, TS, TS, color) def draw_object(tile_x, tile_y, offset, type): if type == -1: return for i in range(0, len(imgs[type]), 2): r, c = ord(imgs[type][i])-33, ord(imgs[type][i+1])-33 col,q = c%23, c//23 pos = q*86+r x,y = pos%16, pos//16 color = COLORS[col] fill_rect((tile_x-offset[0])*TS+x*scale, (tile_y-offset[1])*TS+y*scale, scale, scale, color) def draw_item(X, Y, type): for i in range(0, len(items[type]), 2): r, c = ord(items[type][i])-33, ord(items[type][i+1])-33 col,q = c%23, c//23 pos = q*86+r x,y = pos%16, pos//16 color = COLORS[col] fill_rect(X+x*2, Y+y*2, 2, 2, color) def draw_world(world, plr_x, plr_y, offset, anim): fill_rect(0,0,W,DSP_H*TS,GREEN2) for dsp_y in range(DSP_H): for dsp_x in range(DSP_W): x,y = dsp_x+offset[0], dsp_y+offset[1] tile = world[y*MAPW+x] draw_object(x, y, offset, tile) draw_object(plr_x, plr_y, offset, anim) def draw_last_row(world, plr_x, plr_y, offset, anim): fill_rect(0,(DSP_H-1)*TS,W,TS,GREEN2) dsp_y = DSP_H-1 for dsp_x in range(DSP_W): x,y = dsp_x+offset[0], dsp_y+offset[1] tile = world[y*MAPW+x] draw_object(x, y, offset, tile) if plr_y == dsp_y+offset[1]: draw_object(plr_x, plr_y, offset, anim) def draw_inv_item(i, item, inv, fill=False): x = 4 + (32+4)*i y = H-ECART-4 if fill: fill_rect(x,H-ECART,TS,ECART,GRAY2) if item not in inv: return draw_item(x,y,item) if item not in tools_items: draw_text(str(inv[item]), x+32, y+32, "bottomright", WHITE, BLACK) def draw_inventory(inv): for i, item in enumerate(inv): draw_inv_item(i, item, inv) def draw_band(facing, inv, talking, quest, quest_idx): fill_rect(0,H-ECART,W,ECART,GRAY2) if talking == "trade": draw_inventory(inv) fill_rect(0,H-ECART-32,W,32,GRAY1) x,y = 4, H-ECART-4-32 for i in range(4): i1,a1,i2,a2 = trades[facing][i] if (i2 in tools_items and i2 in inv): draw_text("X", x+32+4, y+20, "center", WHITE, GRAY1) elif (i-1 <= quest_idx[facing]): draw_item(x,y,i1) draw_item(x+32+8,y,i2) text = str(a1)+">"+str(a2) draw_text(text, x+32+4, y+32, "midbottom", WHITE, BLACK) else: draw_text("?", x+32+4, y+20, "center", WHITE, GRAY1) x += 32+8+32+6 elif talking == "quest": fill_rect(0,H-ECART-32,W,32,GRAY1) text = quest[0] draw_text(text, W/2, (DSP_H-1)*TS+TS//2, "center", WHITE, GRAY1) draw_inventory(inv) elif talking == "questgive": draw_text("give your "+str(quest[1][1])+" "+itemnames[quest[1][0]]+"? 1:yes 2:no", W/2, (DSP_H*TS+H)/2, "center", WHITE, GRAY2) elif talking == "questthank": draw_text(quest[2], W/2, (DSP_H*TS+H)/2, "center", WHITE, GRAY2) elif talking: text = talking if isinstance(talking, int): text = talks[facing][talking-1] draw_text(text, W/2, (DSP_H*TS+H)/2, "center", WHITE, GRAY2) elif facing in pnjs: text = "(OK - "+pnjs[facing]+")" draw_text(text, W/2, (DSP_H*TS+H)/2, "center", WHITE, GRAY2) else: draw_inventory(inv) def game(): # Setup world, plr_x, plr_y = create_world() move_timer = 0 offset = [plr_x-plr_x%DSP_W,plr_y-plr_y%DSP_H] anim = 0 inv = {0:1} facing_pos = plr_x+1, plr_y facing = world[facing_pos[1]*MAPW+facing_pos[0]] talking = None quest_idx = {i:0 for i in pnjs} quest = None def trade(i): i1, a1, i2, a2 = trades[facing][i-1] if i2 in tools_items and i2 in inv: return if inv.get(i1,0) >= a1: inv[i1] -= a1 if inv[i1]==0: del inv[i1] if i2 not in inv: inv[i2] = 0 inv[i2] += a2 fill_rect(0,H-ECART,W,ECART,GRAY2) draw_inventory(inv) def do_quest(): quest_idx[facing] += 1 i1, a1 = quest[1] i2, a2 = quest[3] inv[i1] -= a1 if inv[i1]==0: del inv[i1] if i2 not in inv: inv[i2] = 0 inv[i2] += a2 # Dessiner au début fill_rect(0,H-ECART,W,ECART,GRAY2) draw_world(world, plr_x, plr_y, offset, anim) draw_band(facing, inv, talking, quest, quest_idx) # Update while update(keys=[KEY_LEFT, KEY_RIGHT,KEY_UP,KEY_DOWN,KEY_OK, KEY_ONE, KEY_TWO, KEY_THREE, KEY_PLUS, KEY_FOUR]): if just_pressed[KEY_OK]: if talking: # Dialog if isinstance(talking, int): # Continue dialog if talking < len(talks[facing]): talking += 1 # Close dialog elif talking == len(talks[facing]): talking = None draw_band(facing, inv, talking, quest, quest_idx) # Trade elif talking == "trade": talking = None draw_band(facing, inv, talking, quest, quest_idx) draw_last_row(world, plr_x, plr_y, offset, anim) if 1 in inv: end() draw_band(facing, inv, talking, quest, quest_idx) draw_world(world, plr_x, plr_y, offset, anim) continue # Quest elif talking == "quest": its = quest[1] if its[0] in inv and inv[its[0]] >= its[1]: talking = "questgive" else: talking = None draw_band(facing, inv, talking, quest, quest_idx) draw_last_row(world, plr_x, plr_y, offset, anim) elif talking == "questthank": talking = FRIENDSHIP draw_band(facing, inv, talking, quest, quest_idx) # PNJ, ... les trucs qui quitte au OK. elif talking in (TALK_PNJ,FRIENDSHIP, QUEST_NO_NEED): talking = None draw_band(facing, inv, talking, quest, quest_idx) # Open dialog elif facing in pnjs: talking = TALK_PNJ draw_band(facing, inv, talking, quest, quest_idx) # Break prop elif facing in tools and tools[facing][0] in inv: # Erase prop coord = facing_pos[1]*MAPW+facing_pos[0] draw_tile(facing_pos[0],facing_pos[1], offset, FLOOR) # Add item if tools[facing][1] != None: item = tools[facing][1] if item not in inv: inv[item]=0 inv[item] += tools[facing][2] draw_band(facing, inv, talking, quest, quest_idx) # replace tile and facing. world[coord] = facing = -1 # Boutons 1 2 3 + # choisir entre trade quest talk if talking == TALK_PNJ: if just_pressed[KEY_ONE]: talking = "trade" draw_band(facing, inv, talking, quest, quest_idx) elif just_pressed[KEY_TWO]: if quest_idx[facing] == 2: talking = QUEST_NO_NEED else: quest = quests[facing][quest_idx[facing]] talking = "quest" draw_band(facing, inv, talking, quest, quest_idx) elif just_pressed[KEY_THREE]: talking = 1 draw_band(facing, inv, talking, quest, quest_idx) # choisir le trade elif talking == "trade": if just_pressed[KEY_ONE]: trade(1) elif just_pressed[KEY_TWO]: trade(2) elif just_pressed[KEY_THREE]: trade(3) elif just_pressed[KEY_PLUS] or just_pressed[KEY_FOUR]: trade(4) # choisir entre give ou pas elif talking == "questgive": if just_pressed[KEY_ONE]: do_quest() talking = "questthank" draw_band(facing, inv, talking, quest, quest_idx) elif just_pressed[KEY_TWO]: talking = None draw_band(facing, inv, talking, quest, quest_idx) # Direction dx, dy = 0, 0 old_x, old_y = plr_x, plr_y if timer(move_timer, MOVE_COOLDOWN) and not talking: dx -= (just_pressed[KEY_LEFT] and plr_x > 0) dx += (just_pressed[KEY_RIGHT] and plr_x < MAPW - 1) dy -= (just_pressed[KEY_UP] and plr_y > 0 and dx==0) dy += (just_pressed[KEY_DOWN] and plr_y < MAPH - 1 and dx==0) has_moved = dx != 0 or dy != 0 # Animation old_anim = anim if dx < 0: anim = 1 if dx > 0: anim = 0 if dy < 0: anim = 3 if dy > 0: anim = 2 # Collision t = world[(plr_y+dy)*MAPW+(plr_x+dx)] if has_moved and (t not in FLOORED and t!=-1): has_moved = anim != old_anim # Move elif has_moved: plr_x += dx; plr_y += dy move_timer = monotonic() # Facing redraw_band = False if dx != 0 or dy != 0: facing_pos = plr_x+dx, plr_y+dy new_facing = world[facing_pos[1]*MAPW+facing_pos[0]] if in_bounds(facing_pos[0],facing_pos[1]) else -1 redraw_band = (facing in pnjs) != (new_facing in pnjs) facing = new_facing # Draw # Changement de zone if not 0<= plr_x-offset[0] <DSP_W: offset[0] += DSP_W * (-1,1)[plr_x-offset[0] >= DSP_W] draw_world(world, plr_x, plr_y, offset, anim) if not 0<= plr_y-offset[1] <DSP_H: offset[1] += DSP_H * (-1,1)[plr_y-offset[1] >= DSP_H] draw_world(world, plr_x, plr_y, offset, anim) # Joueur a bougé elif has_moved: draw_tile(old_x, old_y, offset, FLOOR) # Restaurer l'ancienne case draw_object(old_x, old_y, offset, world[old_y*MAPW+old_x]) draw_object(plr_x, plr_y, offset, anim) # redessiner la bande quand le joueur rencontre/quitte un pnj if redraw_band: draw_band(facing, inv, talking, quest, quest_idx) def tutorial(): tuto = [ [ '"i want that ruby', ' but i only took 1 gold..."', "Grind and trade with PNJs !", "Do quests to unlock trades !", "(OK: continue)", ], [ 'Arrows: move', 'OK: interact, next dialogs', "OK: quit trade and pnj menu", '1/2/3/4: select trade', "(OK: start)", ], ] idx = 0 def draw_tuto(): fill(BLACK) for i, text in enumerate(tuto[idx]): draw_text(text,W/2,50+i*32,"center",WHITE,BLACK) draw_tuto() while update(keys=[KEY_OK]): if just_pressed[KEY_OK]: if idx == len(tuto)-1: game() else: idx += 1 draw_tuto() def end(): poem = [ [ 'you made it. you got the ruby.', 'thanks for playing.', 'see more of the actual game', " at youtube.com/@aizeir", "(OK: continue)", ], [ 'Ruby Journey Numworks', 'by Aizeir', "(OK: end)", ], ] idx = 0 def draw_end(): fill(BLACK) for i, text in enumerate(poem[idx]): draw_text(text,W/2,50+i*32,"center",WHITE,BLACK) draw_end() while update(keys=[KEY_OK]): if just_pressed[KEY_OK]: if idx == len(poem)-1: return else: idx += 1 draw_end() # Start tutorial()