जेएस पर टिनी ट्रॉन (कोड की 30 लाइनें)

छवि

दरअसल, सप्ताह का रुझान जारी है।

पहली बार जब मैंने एक छोटा सा एक्सेल पढ़ा , तो मैं कुछ ऐसा लिखना चाहता था - छोटा और अच्छा। एक सांप को देखकर - मुझे एहसास हुआ कि यह एक खेल लिखने के लायक था। टिप्पणी पढ़ने के बाद - "मुझे कंपनी की आवाज़ के साथ पैक्समैन चाहिए" मैंने फैसला किया कि मैं कैनवास पर "ऑडियोमैन" लिखूंगा, वेब ऑडियो एपीआई (और वाका-वाका-वाका) के साथ और पृष्ठों को खाकर।

लेकिन यह सच होने के लिए किस्मत में नहीं था, अधिक - कटौती के तहत।

उन लोगों के लिए जो यह सब पढ़ने में रुचि नहीं रखते हैं: नियंत्रण - तीर के साथ, आप इसे किसी भी पृष्ठ पर चला सकते हैं:
jsfiddle , स्रोत।
स्रोत कोड
siteman = { 'settings':{'size' : 10, 'speed' : 5, 'time':new Date().getTime(), 'width':window.innerWidth, 'height':window.innerHeight}, 'coord':{'x' : 0 + 20, 'y' : 0 + 20}, // plus siteman size 'direction':{ 'current':{'x': 0.75 * Math.PI, 'y' : 1.75 * Math.PI, 'clock' : false, 'calc_x' : function(){ return siteman.coord.x + siteman.settings.speed}, 'calc_y' : function(){return siteman.coord.y}}, 37:{'x': 0.75 * Math.PI, 'y' : 1.75 * Math.PI, 'clock' : true, 'calc_x' : function(){ return siteman.coord.x - siteman.settings.speed}, 'calc_y' : function(){return siteman.coord.y}}, 38:{'x': 1.75 * Math.PI, 'y' : 0.75 * Math.PI, 'clock' : false, 'calc_x' : function(){ return siteman.coord.x}, 'calc_y' : function(){return siteman.coord.y - siteman.settings.speed}}, 39:{'x': 0.75 * Math.PI, 'y' : 1.75 * Math.PI, 'clock' : false, 'calc_x' : function(){ return siteman.coord.x + siteman.settings.speed}, 'calc_y' : function(){return siteman.coord.y}}, 40:{'x': 1.75 * Math.PI, 'y' : 0.75 * Math.PI, 'clock' : true, 'calc_x' : function(){ return siteman.coord.x}, 'calc_y' : function(){return siteman.coord.y + siteman.settings.speed}} }, 'ctx':document.body.appendChild((function(element){element.width=window.innerWidth; element.height=window.innerHeight; element.style.cssText='background:rbga(60, 40, 20, 1); position:absolute; top:0; z-index: 100000000;'; return element;})(document.createElement('canvas'))).getContext("2d"), 'h_ctx':new function(){this.chain = function(method, args){siteman.ctx[method].apply(siteman.ctx, args); return this;}}, 'checkCollision':function(data){return data[0] == 128 && data[1] == 128 && data[2] == 128;} }; siteman.ctx.fillStyle = "rgb(128, 128, 128)"; siteman.h_ctx.chain('beginPath').chain('fillRect', [0, 0, window.innerWidth, window.innerHeight]); (function game_loop(){ siteman.coord = {'x':siteman.direction.current.calc_x(), 'y':siteman.direction.current.calc_y()}; siteman.ctx.fillStyle = "rgb(255, 255, 0)"; siteman.h_ctx.chain('beginPath').chain('arc', [siteman.coord.x, siteman.coord.y, siteman.settings.size, 0.25 * Math.PI, 1.25 * Math.PI, siteman.direction.current.clock]).chain('fill') siteman.h_ctx.chain('beginPath').chain('arc', [siteman.coord.x, siteman.coord.y, siteman.settings.size, siteman.direction.current.x, siteman.direction.current.y, siteman.direction.current.clock]).chain('fill'); var offset_x = siteman.settings.size * (siteman.coord.x != siteman.direction.current.calc_x() ? (siteman.direction.current.clock ? -1 : 1) : 0), offset_y = siteman.settings.size * (siteman.coord.y != siteman.direction.current.calc_y() ? (siteman.direction.current.clock ? 1 : -1) : 0); if(!siteman.checkCollision(siteman.ctx.getImageData(siteman.coord.x + offset_x, siteman.coord.y + offset_y,1,1).data)){ alert('Game over. Your score is: '+(new Date().getTime() - siteman.settings.time)+'. Siteman size: '+siteman.settings.size+' and speed:'+siteman.settings.speed+', map width: '+siteman.settings.width+' and height: '+siteman.settings.height); }else{ setTimeout(function(){game_loop();}, 1000 / 60); //requestAnimationFrame(game_loop); } })(); document.addEventListener('keydown', function (e) {siteman.direction.current=siteman.direction[e.keyCode] || siteman.direction.current}, false); 



यह सब कैसे शुरू हुआ?


"जेएस पर 30 लोअरकेस अनुप्रयोगों के मैराथन" से बहुत पहले मैं अपनी खुद की मिनी गेम लिखना चाहता था - नई प्रौद्योगिकियों को मास्टर करने के लिए और "गेम में शामिल हों"। लेकिन, यह समझने के बाद कि परिणामी कोड बकवास से भरा है, यह खराब बदबू आ रही है और इसे फिर से लिखने की जरूरत है - किसी तरह मैंने जारी रखने के लिए अपना उत्साह खो दिया, हालांकि मेरे पास अभी भी कैनवास के साथ काम करने के कुछ कौशल हैं। हां, और मैंने जारी रखने की उम्मीद कभी नहीं छोड़ी।

और अब मौका कुछ छोटा और दिलचस्प करने के लिए बदल गया है। विकल्प उस व्यक्ति पर गिर गया, जो साइट को नष्ट कर देता है, कालापन पीछे छोड़ देता है, लेकिन परिणाम एक खिलाड़ी के लिए ट्रॉन ट्रेनिंग रूम था।

यह सब क्या है?


गणित के एक छोटे से ढेर के बारे में (पहली बार जब मैंने कैनवास पर आवश्यक लंबाई के एक खंड के निर्माण में 3 दिन बिताए), टक्करों की गणना, वांछित आकार की आकृतियाँ और सामान्य और असामान्य प्रोग्रामिंग के अन्य गुर आकर्षित करना। संक्षेप में, क्योंकि अधिकांश कोड तुच्छ है।

मैं मानता हूं, कुछ लाइनें बहुत लंबी हैं, उदाहरण के लिए, कैनवास के निर्माण के साथ एक रेखा (11)। लेकिन, विचार करें कि यह एक अमूर्त है, जैसे "ड्रॉ ​​ए सिटमैन", "बिल्ड कैनवस", "परिणाम का उत्पादन।" कुछ चरों की लंबाई कम करना भी संभव होगा, लेकिन हम JS1K नहीं खेल रहे हैं, है ना?

क्या इस कोड को दिलचस्प बनाता है?


0) तर्क:
यह सरल है - हम सिटमैन को इनिशियलाइज़ करते हैं, उसके गुणों को परिभाषित करते हैं, पेज के ऊपर एक कैनवास खींचते हैं, सभी कीज़ को दबाने के लिए बाँधते हैं और केवल कुछ लोगों को "सुनते हैं" और सिटमैन को भी प्रदर्शित करते हैं, मुख्य लूप में टकराव की गणना करते हैं।

1) चेनिंग लागू करने से:

 //    source 'h_ctx':new function(){this.chain = function(method, args){siteman.ctx[method].apply(siteman.ctx, args); return this;}} /*     this    -   --,  this     window,       .  ,  this      ,   h_ctx     ,        - siteman.ctx[method].apply(siteman.ctx, args)     "  ", .apply -  ,    this   .  ""  */ siteman.h_ctx.chain('beginPath').chain('arc'... /*    */ siteman.ctx.beginPath(); siteman.ctx.arc(... /*   30         */ 


2) सिटमैन ड्राइंग। इसमें दो भरे हुए आधे आधे वृत्त शामिल हैं (टिप के लिए इस लेख के लिए धन्यवाद, उनमें से एक "स्थिर" है (केवल भरने का क्रम बदलता है - दक्षिणावर्त या वामावर्त), दूसरा अपने निर्देशांक को बदलता है जब आंदोलन की दिशा बदल जाती है (ऊपर + नीचे - बाएं + सही करने के लिए), वास्तव में इस तरह से यह पैक्मैन की एक ड्राइंग को समायोजित करने के लिए काफी कॉम्पैक्ट निकला, जो सभी दिशाओं में दिखता है।

सबसे पहले मैं सामान्य रूप से आंदोलन की स्थिति का वर्णन करना चाहता था, तब मैंने महसूस किया कि इसमें बहुत अधिक स्थान है, क्योंकि मैंने आंदोलन की दिशा वाले ऑब्जेक्ट में सीधे सभी आवश्यक सूत्र लिखे थे। नतीजतन, हमारे पास वही है जो हमारे पास है

 /*  -   -*/ siteman.h_ctx.chain('beginPath') .chain('arc', [siteman.coord.x, siteman.coord.y, siteman.settings.size, 0.25 * Math.PI, 1.25 * Math.PI, siteman.direction.current.clock]) .chain('fill') /*        */ siteman.h_ctx.chain('beginPath') .chain('arc', [siteman.coord.x, siteman.coord.y, siteman.settings.size, siteman.direction.current.x, siteman.direction.current.y, siteman.direction.current.clock]) .chain('fill'); 


3) टकराव की गणना:

 /* .  ""   -   ""    ,  ,  siteman              ,     "" ,                  */ var offset_x = siteman.settings.size * (siteman.coord.x != siteman.direction.current.calc_x() ? (siteman.direction.current.clock ? -1 : 1) : 0), offset_y = siteman.settings.size * (siteman.coord.y != siteman.direction.current.calc_y() ? (siteman.direction.current.clock ? 1 : -1) : 0); /*   ,          128( ,   ).       ,    -.      ,     */ if(!siteman.checkCollision(siteman.ctx.getImageData(siteman.coord.x + offset_x, siteman.coord.y + offset_y,1,1).data)) 

यह कैसे काम करता है और क्यों इस तरह के सूत्र हैं? यदि x या y के साथ समन्वय बदलता है, तो आपको इस समन्वय के साथ ऑफसेट को ध्यान में रखना होगा (वैसे, आप समग्र आंदोलनों को भी जोड़ सकते हैं), अन्यथा ध्यान में न रखें। सर्कल (घड़ी की दिशा या वामावर्त) को कैसे भरें, हम आंदोलन की दिशा को समझते हैं, और या तो आकार द्वारा एक ऑफसेट को घटाते या जोड़ते हैं।
अंत में, हम जोड़ते हैं कि हमें निर्देशांक में क्या मिला, क्योंकि हम जो हमारे सामने हैं उसमें रुचि रखते हैं (हम इसे दूर ले जाते हैं - बाद में)।
निर्देशांक की गणना करने के सूत्र उन लोगों के समान हैं जो मैं मूल रूप से लूप का निर्माण करता था।

4) अच्छी तरह से, कैनवास के निर्माण से थोड़ा सा, लेकिन यह विकृत है, इसलिए मैंने इसे नहीं समझाया, यह कभी भी अच्छा अभ्यास नहीं है।

कोड requestAnimationFrame और setTimeout से दोनों काम करता है। सेटटाइमआउट डिफ़ॉल्ट के लायक क्यों है? क्योंकि लाइनक्स पर मैं एक लाइन पर "पॉलीफ़िल" नहीं चला सकता, इसलिए यह अधिक स्थिर है।

यह कोड क्यों खराब है?


1) आप एक सिटमैन को क्लोन नहीं कर सकते। यदि यह संभव था - 100% यह संभव होगा कि साइटमैप की एक छोटी सी फैक्ट्री में सामान हो और कम से कम कुछ प्रतिद्वंद्वी हों। अब मैं इसे देखता हूं, लेकिन मैं तीसरी बार सब कुछ फिर से लिखना नहीं चाहता हूं।
2) खाली पेज पर ड्राइव करना थोड़ा उबाऊ है। यह एक ट्रॉन की तुलना में इस तरह के फास्ट-ईट वसा सांप निकला।
3) कुछ पंक्तियों में बहुत अधिक (हर मायने में) अमूर्तता है।
4) फिर भी, यह पिछले तनाव से डेल्टा के माध्यम से गिनती करने के लिए अधिक सही होगा और केवल जब वह कर सकता है, तब साइमन को स्थानांतरित करें।
5) ठीक है, कोनों पर चित्र थोड़ा अजीब लग रहा है, लेकिन यहां आपको एक पैक्मैन नहीं बल्कि एक पूरे सर्कल को खींचना है, या निर्देशांक के साथ बिगाड़ना भी अधिक है।
6) हां, आप खुद खा सकते हैं। यदि आप आंदोलन के विपरीत कुंजी दबाते हैं। चूंकि आंदोलन की दिशा स्पष्ट रूप से कहीं भी इंगित नहीं की गई है - कुंजी बाइंडिंग के साथ एक भारी स्ट्रिंग प्राप्त की जाएगी, लेकिन ऐसा करना काफी संभव है।
7) पर्याप्त रीसेट नहीं

हां, और लंबे समय तक मैंने सामान्य लूप बनाने की कोशिश की, लेकिन यदि आप दिशा को ध्यान में रखते हैं (और "सरल" लूप नहीं बनाते हैं जो हमेशा पीछे-पीछे रहेगा), तो आपको बहुत अधिक कोड और सूत्र मिलते हैं। ऑडियो के साथ एक ही, कम से कम 3 लाइनों पर खर्च किया जाना चाहिए:
 siteman.audio = new Audio(data:wav/base64); siteman.audio.loop=true; siteman.audio.play(); 

लेकिन यह एक तथ्य नहीं है कि वे ज्यादातर मामलों में तुरंत काम करना शुरू कर देंगे।

तो आगे क्या है?


लेकिन कुछ भी नहीं। लक्ष्य कैनवस का उपयोग करते हुए, 30 लाइनों पर एक गेम बनाने का था - यह किया गया था। कोड यूजी नहीं, बल्कि सर्वश्रेष्ठ नहीं निकला। लेकिन मुझे बहुत कुछ मिला, और फिर भी मैंने किसी तरह का खेल बनाया।

सच है, मैं अभी भी बेहतर करना जारी रखूंगा, विशेष रूप से मैं एक साधारण एआई जोड़ना चाहूंगा जो दीवारों को उछाल देगा और बेतरतीब ढंग से आगे बढ़ेगा, लेकिन इसके लिए मुझे गंभीरता से कोड को फिर से लिखना होगा, और इस तथ्य को नहीं कि मैं अधिक या कम पठनीय की 30 पंक्तियों में फिट होगा। कोड। खैर, या फिर भी मैं एक साइट खाने वाले के साथ विचार समाप्त कर दूंगा। लेकिन यह उस समय के लिए अफ़सोस की बात है, जब इस परियोजना पर कुल 5 घंटे बिताए गए थे और इस पर कुछ और शामें बिताना नहीं चाहते थे।

PS मैंने व्यंग्यात्मक लेख "js-code सिर्फ एक पंक्ति" पढ़ा है, और IMHO - बिंदु बिल्कुल N रेखाएँ बनाने के लिए नहीं है (अधिकांश भाषाएँ आपको कम से कम 1 पंक्ति को संक्षिप्त करने की अनुमति देती हैं), लेकिन बिंदु कुछ लिखने की है मजाकिया और छोटा।

Source: https://habr.com/ru/post/In202874/


All Articles