यह दुनिया कितनी खूबसूरत हैकंसोल.लॉग () वेब कंसोल को डिबगिंग जानकारी को आउटपुट करने के लिए एक अच्छी विधि है। आप संख्या, स्ट्रिंग्स, सरणियाँ, ऑब्जेक्ट्स, फ़ंक्शंस, सादे पाठ प्रदर्शित कर सकते हैं, और इसके अलावा, आप इन सभी को स्वरूपण, रंग, पृष्ठभूमि और काफी कुछ अन्य शैलियाँ जोड़ सकते हैं ... क्या यह सब है? क्या यह सब विधि अकेले कर सकती है? अच्छी तरह से ... एक सरल platformer, रे कास्टिंग एल्गोरिथ्म, या ऊतक भौतिकी के कंसोल में कार्यान्वयन के बारे में क्या?
जो लोग सिर्फ देखने के लिए यहां आए हैं, मैं शुरुआत में ही डेमो के लिए एक लिंक छोड़ दूंगा:
गीथुब: जीथुबलाइव उदाहरण: डेमोपृष्ठ खोलें, F12 दबाएं, कंसोल को व्यापक रूप से फैलाएं और उस डेमो पर जाएं जो आपकी रुचि है। और निश्चित रूप से आपको कंसोल में छवि को नियंत्रित करने में सक्षम होने के लिए पृष्ठ पर ध्यान केंद्रित करने की आवश्यकता है।
यह क्रोम में चलाने के लिए सलाह दी जाती है, लेकिन एक ऐसा मामला हो सकता है जहां चित्र प्रदर्शित करने के लिए उपयोग किए जाने वाले वर्णों का समर्थन नहीं किया जा सकता है और वर्गों के रूप में प्रदर्शित किया जा सकता है। एक विकल्प के रूप में, अपने लिए कोड डाउनलोड करें और आउटपुट वर्णों को दूसरों में बदलें।
और अब इस बारे में थोड़ा और
एक कैनवास के रूप में कंसोल
आइए कंसोल.लॉग () विधि और कंसोल को एक डीबगिंग टूल के रूप में नहीं, बल्कि एक कैनवास के रूप में देखें। हां, एक ऐसी जगह के रूप में जहां हम थोड़ा आकर्षित कर सकते हैं और यहां तक कि इसे स्थानांतरित भी कर सकते हैं। इसके अलावा, किसी ने भी यूनिकोड वर्णों को रद्द नहीं किया।
मैंने कंसोल में "ड्राइंग" के तरीकों को लागू किया, जैसे कि कैनवास के साथ काम करने के तरीके। लेकिन एक असली कैनवास की तुलना में, कंसोल को आउटपुट और, इसके अलावा, इसके रिवर्डिंग महान सीमाएं लगाते हैं, जो दुर्भाग्य से खतना नहीं किया जा सकता है (कम से कम मुझे ऐसा लगता है)। क्रम में उनके बारे में।
पिक्सेल का आकार
कैनवास पर ड्राइंग करते समय, हम पिक्सेल के साथ काम कर रहे हैं, जिसका आकार, ध्यान, पिक्सेल आपके मॉनिटर पर है! कंसोल में प्रदर्शित होने पर, "पिक्सेल" एक अलग अवधारणा पर ले जाता है। हां, कंसोल के संबंध में, यह इसकी अजीबोगरीब पिक्सेल है, लेकिन असली पिक्सेल के संबंध में, क्या यह सिर्फ एक विशेष चरित्र है, उदाहरण के लिए? लेकिन पात्रों पर थोड़ा प्रतिबंध है, या एक सिफारिश है: इसमें कंसोल में लाइन ब्रेक की ऊंचाई के बराबर ऊंचाई होनी चाहिए। लेकिन यह केवल तभी है जब हम एक सुंदर चित्र प्राप्त करना चाहते हैं (जितना संभव हो)।
पुनः बनाने
चूंकि यह मुख्य समस्या है कंसोल को अक्सर डेटा अपडेट करने के लिए डिज़ाइन नहीं किया गया है। हम उन्हें वहां लाते हैं, घटाते हैं और घटाते हैं। कंसोल है। क्लियर () जो इसे साफ़ करता है, लेकिन मुझे लगता है कि इसका उपयोग बहुत कम किया जाता है। अरे हां, लेकिन मेरे मामले में नहीं, जहां सब कुछ इस तथ्य पर आधारित है कि आपको इसे लगातार साफ करने और पाठ को फिर से प्रदर्शित करने की आवश्यकता है। यहाँ सिर्फ एक कंसोल है। क्लियर () इसके पूर्ण अधिभार का कारण बनता है, जो एक मिलीसेकंड फ्लैशिंग के साथ होता है। और अगर आपको इसे लगातार कुछ आवृत्ति के साथ फिर से तैयार करने की आवश्यकता है, तो अतिसंवेदनशीलता वाले लोग इसे नहीं देखना बेहतर है। लेकिन दुर्भाग्य से इसके बारे में कुछ नहीं किया जा सकता है।
रंग
जैसा कि मैंने शुरुआत में लिखा था, स्वरूपण आउटपुट पर लागू किया जा सकता है, लेकिन मेरे मामले में मैंने एक काले और सफेद छवि के साथ संतुष्ट नहीं होने का फैसला किया, जिसे यूनिकोड वर्णों की एक विस्तृत चयन के लिए धन्यवाद प्राप्त किया जा सकता है।
लाइव उदाहरणों पर अधिक विस्तृत सीमाएं देखी जा सकती हैं, जिनके लिंक मैंने लेख के अंत में छोड़ दिए थे। आप पहले से ही उनके साथ खुद को परिचित कर सकते हैं, लेकिन अब मैं खुद ड्राइंग प्रक्रिया का वर्णन करूंगा। यह सब मैंने एक छोटी सी लाइब्रेरी में डिज़ाइन किया है जिसके साथ अंत में मैं सरल गेम और रेकास्टिंग एल्गोरिथ्म को लागू करता हूं
हम कंसोल में आकर्षित करते हैं
मैंने विधियों के नाम, साथ ही कैनवास से ड्राइंग प्रक्रिया को अपनाया (बाद में मैं इसका वर्णन करूंगा क्यों) और यह क्या समाप्त हुआ
engine.jsconst canvas = { width: 70, height: 40, getContext(type) { if (type != '2d') { return console.log('Only 2d'); } return new Context2D(type); } } class Context2D { constructor(type) { this.fillStyle = '?'; this.emptyStyle = '?'; this.map = []; for (let i = 0; i < canvas.height; i++) { this.map[i] = []; for (let j = 0; j < canvas.width; j++) { this.map[i][j] = this.emptyStyle; } } this.path = []; this.clear(); } fillRect(x, y, width, height) { for (let i = y; i < y + height; i++) { for (let j = x; j < x + width; j++) { if (!this.map[i]) break; this.map[i][j] = this.fillStyle; } } this.draw(); } strokeRect(x, y, width, height) { for (let j = x; j < x + width; j++) { this.map[y][j] = this.fillStyle; this.map[y + height - 1][j] = this.fillStyle; } for (let i = y + 1; i < y + height - 1; i++) { this.map[i][x] = this.fillStyle; this.map[i][x + width - 1] = this.fillStyle; } this.draw(); } clearRect(x, y, width, height) { for (let i = y; i < y + height; i++) { for (let j = x; j < x + width; j++) { this.map[i][j] = this.emptyStyle; } } this.draw(); } beginPath() { this.path = []; } moveTo(x, y) { this.path.push([Math.round(x), Math.round(y), true]); } lineTo(x, y) { this.path.push([Math.round(x), Math.round(y)]); } closePath() { if (!this.path.length) return false this.path.push([this.path[0][0], this.path[0][1]]); } stroke() { const path = this.path; for (let i = 0; i < path.length - 1; i++) { const x0 = path[i][0]; const y0 = path[i][1]; const x1 = path[i+1][0]; const y1 = path[i+1][1]; this.fillPixel(x1, y1); if (path[i+1][2]) continue; const deltaX = Math.abs(x1 - x0); const deltaY = Math.abs(y1 - y0); const signX = x0 < x1 ? 1 : -1; const signY = y0 < y1 ? 1 : -1; let error = deltaX - deltaY; let x = x0; let y = y0; while(x !== x1 || y !== y1) { this.fillPixel(x, y) const error2 = error * 2; if (error2 > -deltaY) { error -= deltaY; x += signX; } if (error2 < deltaX) { error += deltaX; y += signY; } } } this.draw(); } fillPixel(x, y) { if (!this.map[y]) return false; this.map[y][x] = this.fillStyle; } arc(x1, y1, r) { let x = 0; let y = r; let delta = 1 - 2 * r; let error = 0; while (y >= 0) { this.moveTo(x1 + x, y1 + y); this.moveTo(x1 + x, y1 - y); this.moveTo(x1 - x, y1 + y); this.moveTo(x1 - x, y1 - y); error = 2 * (delta + y) - 1; if (delta < 0 && error <= 0) { delta += 2 * ++x + 1; continue; } if (delta > 0 && error > 0) { delta -= 2 * --y + 1; continue; } delta += 2 * (++x - y--); } this.draw() } draw() { this.clear();
अब हम इस फाइल को html फाइल में शामिल करते हैं, कंसोल खोलें और कई तरीकों को आजमा सकते हैं
canvas.width = 70 canvas.height = 30 const ctx = canvas.getContext('2d') ctx.beginPath() ctx.moveTo(30, 5) ctx.lineTo(30, 25) ctx.moveTo(30, 15) ctx.lineTo(35, 13) ctx.lineTo(38, 13) ctx.lineTo(40, 16) ctx.lineTo(40, 25) ctx.stroke()
यहाँ परिणाम है

आउटपुट एक ऐसी छवि है जिसकी मैंने कल्पना की थी, सब कुछ निर्देशांक में और कैनवास के साथ सादृश्य द्वारा तैयार किया गया है।
शांत उदाहरण
मेरी योजना यह थी कि कंसोल में एक नियमित कैनवास गेम को गेम में यथासंभव सरल रूप से स्थानांतरित करना संभव हो। इसके लिए, मैंने न्यूनतम बदलावों के साथ समान तरीके लागू किए। इसका क्या मतलब है? और यह तथ्य कि किसी भी गेम को लागू करने के लिए मैं बस कैनवास पर तैयार-निर्मित लेता हूं, मैं कोड की कुछ पंक्तियों को सही करता हूं और यह कंसोल में शुरू होता है!
वास्तव में यही मैंने किया है। और पहली बात जो मेरे साथ हुई (छोटे वर्ग को छोड़कर जो सांत्वना के चारों ओर ले जाई जा सकती है) रायकोटिंग एल्गोरिथ्म को लागू करना था
मैंने स्वयं एल्गोरिथ्म नहीं लिखा था, लेकिन बस इसे
यहाँ उधार
दिया और, कई लाइनों को बदलने के बाद, मैंने इसे कंसोल में लॉन्च किया।

यह प्रभावशाली लगता है, है ना?
यहाँ कुछ और स्क्रीनशॉट हैं जो मैंने कंसोल में स्थानांतरित किए हैं।
साँप
ऊतक के भौतिकी जो चिकने और फटे हुए भी हो सकते हैंफिर, इस साँप और ऊतक भौतिकी का कार्यान्वयन मेरा नहीं है, मैंने इसे कंसोल के लिए अनुकूलित किया। स्रोत फ़ाइलों में, मैंने मूल स्रोतों से लिंक छोड़ दिए।