ทางเลือกที่ยืดหยุ่นสำหรับคลาส polymorphic ขนาดเล็กจำนวนมาก (เพื่อใช้เป็นคุณสมบัติหรือข้อความหรือเหตุการณ์) C ++


9

เกมของฉันมีสองคลาสที่มีประโยชน์มาก แต่ก็ค่อยๆเจ็บปวด ข้อความและคุณสมบัติ (คุณสมบัติเป็นส่วนประกอบหลัก)

พวกเขาทั้งคู่มาจากคลาสพื้นฐานและมีสแตติก id เพื่อให้ระบบสามารถให้ความสนใจกับสิ่งที่พวกเขาต้องการ มันทำงานได้ดีมาก ... ยกเว้น ...

ฉันกำลังสร้างประเภทข้อความและประเภทคุณสมบัติใหม่อยู่ตลอดเวลาขณะที่ฉันขยายเกม ทุกครั้งที่ฉันต้องเขียนไฟล์ 2 ไฟล์ (hpp และ cpp) และสำเร็จรูปจำนวนมากเพื่อให้ได้ classID และหนึ่งหรือสองชนิดข้อมูลมาตรฐานหรือตัวชี้

มันเริ่มที่จะทำให้การเล่นและการทดสอบความคิดใหม่ ๆ เป็นงานที่น่าเบื่อ ฉันต้องการเมื่อฉันต้องการสร้างข้อความใหม่หรือประเภทคุณสมบัติฉันต้องการให้สามารถพิมพ์บางสิ่งเช่น

ShootableProperty:  int gunType, float shotspeed;

ItemCollectedMessage:  int itemType;

แทนการสร้างไฟล์ส่วนหัวและ cpp เขียนตัวสร้างรวมถึงผู้ปกครองชั้น ฯลฯ ฯลฯ

มันอยู่ที่ประมาณ 20 - 40 บรรทัด (รวมถึงยามและทุกอย่าง) เพื่อทำในสิ่งที่เป็นตรรกะใน 1 หรือ 2 บรรทัดในใจของฉัน

มีรูปแบบการเขียนโปรแกรมเพื่อหลีกเลี่ยงปัญหานี้หรือไม่?

เกี่ยวกับการเขียนสคริปต์ (ซึ่งฉันไม่รู้อะไรเลย) ... มีวิธีกำหนดคลาสเรียนที่เกือบจะเหมือนกันหรือไม่?


นี่คือลักษณะของคลาสที่หนึ่ง:

// Velocity.h

#ifndef VELOCITY_H_
#define VELOCITY_H_

#include "Properties.h"

#include <SFML/System/Vector2.hpp>

namespace LaB
{
namespace P
{

class Velocity: public LaB::Property
{
public:
    static const PropertyID id;

    Velocity(float vx = 0.0, float vy = 0.0)
    : velocity(vx,vy) {}
    Velocity(sf::Vector2f v) : velocity(v) {};

    sf::Vector2f velocity;
};

} /* namespace P */
} /* namespace LaB */
#endif /* LaB::P_VELOCITY_H_ */



// Velocity.cpp

#include "Properties/Velocity.h"

namespace LaB
{
namespace P
{

const PropertyID Velocity::id = Property::registerID();

} /* namespace P */
} /* namespace LaB */

ทั้งหมดนี้เป็นเพียงเวกเตอร์ 2 มิติและรหัสที่บอกว่าคาดหวังเวกเตอร์ 2 มิติ (ได้รับคุณสมบัติบางอย่างมีองค์ประกอบที่ซับซ้อนมากขึ้น แต่เป็นความคิดเดียวกัน)


3
ลองดูที่นี่มันอาจช่วยคุณได้ gameprogrammingpatterns.com/type-object.html

1
ทั้งหมดนี้ดูเหมือนว่าเทมเพลตอาจช่วยได้ แต่ไม่ใช่กับการเริ่มต้นแบบคงที่ ในกรณีนี้สามารถทำให้ง่ายขึ้นมากในกรณีนี้ แต่เป็นการยากที่จะบอกโดยไม่มีข้อมูลเพิ่มเติมเกี่ยวกับสิ่งที่คุณต้องการทำกับ ID เหล่านั้นและสาเหตุที่คุณใช้การสืบทอดเลย การใช้การสืบทอดสาธารณะ แต่ไม่มีฟังก์ชั่นเสมือนเป็นกลิ่นรหัสแน่นอน ... นี่ไม่ใช่ความหลากหลาย!
ltjax

คุณพบห้องสมุดบุคคลที่สามที่ใช้งานหรือไม่
Boris

คำตอบ:


1

C ++ มีประสิทธิภาพ แต่ก็อย่างละเอียด หากสิ่งที่คุณต้องการคือคลาสโพลิมอร์ฟิคขนาดเล็กจำนวนมากที่แตกต่างกันทั้งหมดใช่แล้วมันจะต้องใช้ซอร์สโค้ดจำนวนมากเพื่อประกาศและกำหนด ไม่มีอะไรเกี่ยวข้องกับเรื่องนี้จริงๆ

ทีนี้อย่างที่ ltjax กล่าวว่าสิ่งที่คุณกำลังทำอยู่ที่นี่นั้นไม่ได้มีความแตกต่างกันมากอย่างน้อยก็สำหรับรหัสที่คุณให้ไว้ ฉันไม่เห็นอินเทอร์เฟซทั่วไปที่จะซ่อนการใช้งานเฉพาะของคลาสย่อย ยกเว้นบางทีสำหรับรหัสประจำชั้น แต่จริงๆแล้วนี้ซ้ำซ้อนกับรหัสชั้นเรียนจริง: ชื่อ ดูเหมือนว่าจะเป็นเพียงกลุ่มคลาสที่มีข้อมูลบางอย่างไม่มีอะไรซับซ้อนจริงๆ

แต่สิ่งนี้ไม่ได้แก้ปัญหาของคุณ: คุณต้องการสร้างข้อความและคุณสมบัติมากมายด้วยรหัสจำนวนน้อยที่สุด รหัสน้อยหมายถึงข้อบกพร่องน้อยลงดังนั้นนี่เป็นการตัดสินใจที่ชาญฉลาด น่าเสียดายสำหรับคุณไม่มีวิธีแก้ปัญหาเดียว เป็นการยากที่จะบอกว่าสิ่งใดเหมาะสมกับความต้องการของคุณมากที่สุดโดยไม่ทราบว่าคุณตั้งใจจะทำอะไรกับข้อความและคุณสมบัติเหล่านั้น ดังนั้นให้ฉันแค่เปิดเผยตัวเลือกของคุณ:

  1. การใช้ภาษา C ++ แม่ เทมเพลตเป็นวิธีที่ยอดเยี่ยมในการให้คอมไพเลอร์ "เขียนโค้ด" ให้คุณ มันมีมากขึ้นและโดดเด่นในโลก C ++ เนื่องจากภาษาพัฒนาขึ้นเพื่อรองรับพวกเขาได้ดีขึ้น (เช่นตอนนี้คุณสามารถใช้ตัวแปรเทมเพลตจำนวนตัวแปรได้ ) มีระเบียบวินัยทั้งที่ทุ่มเทให้กับคนรุ่นอัตโนมัติรหัสผ่านแม่แบบเป็น: แม่แบบ metaprogramming ปัญหาคือ: มันยาก อย่าคาดหวังว่าผู้ที่ไม่ใช่โปรแกรมเมอร์จะสามารถเพิ่มคุณสมบัติใหม่ได้ด้วยตนเองหากคุณวางแผนที่จะใช้เทคนิคดังกล่าว

  2. ใช้ธรรมดาเก่าแมโคร C เป็นโรงเรียนเก่าง่ายต่อการล่วงละเมิดและมีแนวโน้มที่ผิดพลาด พวกเขายังง่ายมากในการสร้าง มาโครเป็นเพียงแค่การทำสำเนาคัดสรรที่ดำเนินการโดยพรีโพรเซสเซอร์ แต่อย่าคาดหวังว่าโปรแกรมเมอร์คนอื่นจะรักคุณเพราะพวกเขามักใช้มาโครเพื่อซ่อนข้อบกพร่องในการออกแบบโปรแกรมโดยรวม แม้ว่าบางครั้งพวกเขามีประโยชน์

  3. อีกทางเลือกหนึ่งคือการใช้เครื่องมือภายนอกเพื่อสร้างรหัสให้คุณ มันถูกกล่าวถึงแล้วในคำตอบก่อนหน้านี้ดังนั้นฉันจะไม่ขยายที่

  4. มีภาษาอื่น ๆ ที่มีความละเอียดน้อยกว่าและจะช่วยให้คุณสร้างวิธีการเรียนได้ง่ายขึ้น ดังนั้นหากคุณมีการผูกสคริปต์อยู่แล้ว (หรือคุณวางแผนที่จะใช้มัน) การกำหนดคลาสเหล่านั้นในสคริปต์อาจเป็นตัวเลือก การเข้าถึงจาก C ++ นั้นค่อนข้างซับซ้อนและคุณจะเสียประโยชน์จากการสร้างคลาสที่ง่ายขึ้น ดังนั้นนี่น่าจะเป็นไปได้เท่านั้นที่คุณวางแผนที่จะทำตรรกะของเกมส่วนใหญ่ในภาษาอื่น

  5. สุดท้ายสุดท้าย แต่ไม่น้อยคุณควรพิจารณาใช้การออกแบบที่ขับเคลื่อนด้วยข้อมูล คุณสามารถกำหนด "คลาส" เหล่านั้นในไฟล์ข้อความอย่างง่ายโดยใช้เลย์เอาต์ที่คล้ายกับที่คุณเสนอด้วยตนเอง คุณจะต้องสร้างรูปแบบที่กำหนดเองและตัวแยกวิเคราะห์มันหรือใช้หนึ่งในหลาย ๆ ตัวเลือกที่มีอยู่แล้ว (.ini, XML, JSON และ whatnot) จากนั้นในด้าน C ++ คุณจะต้องสร้างระบบที่รองรับการรวบรวมวัตถุประเภทต่าง ๆ เหล่านั้น นี่เกือบเทียบเท่ากับวิธีการเขียนสคริปต์ (และอาจต้องใช้งานมากขึ้น) ยกเว้นคุณจะสามารถปรับแต่งให้ตรงกับความต้องการของคุณได้แม่นยำยิ่งขึ้น และถ้าคุณทำให้มันง่ายพอโปรแกรมที่ไม่ใช่โปรแกรมเมอร์ก็สามารถสร้างสิ่งใหม่ได้ด้วยตัวเอง


0

เครื่องมือสร้างรหัสจะช่วยคุณได้อย่างไร

ตัวอย่างเช่นคุณสามารถกำหนดประเภทข้อความและสมาชิกในไฟล์ข้อความขนาดเล็กและมีเครื่องมือรหัส gen แจงและเขียนไฟล์ C ++ สำเร็จรูปทั้งหมดเป็นขั้นตอนที่สร้างไว้ล่วงหน้า

มีวิธีแก้ปัญหาที่มีอยู่เช่น ANTLR หรือ LEX / YACC และมันก็ไม่ยากที่จะม้วนตัวเองขึ้นอยู่กับความซับซ้อนของคุณสมบัติและข้อความของคุณ


ทางเลือกเดียวกับ LEX / YACC aproach เมื่อฉันต้องสร้างไฟล์ที่คล้ายกันมากกับการแก้ไขเล็กน้อยฉันใช้สคริปต์ python ที่ง่ายและเล็กและไฟล์เทมเพลตรหัส C ++ ที่มีแท็ก สคริปต์ python ค้นหาแท็กเหล่านี้ในเทมเพลตแทนที่ด้วยโทเค็นตัวแทนขององค์ประกอบที่กำลังสร้าง
ผู้ชนะ

0

ฉันแนะนำให้คุณศึกษาเกี่ยวกับ Protocol Buffers ของ Google ( http://code.google.com/p/protobuf/ ) นี่เป็นวิธีที่ชาญฉลาดในการจัดการข้อความทั่วไป คุณเพียงแค่ต้องระบุคุณสมบัติในรูปแบบ struct-llike และตัวสร้างโค้ดทำงานทั้งหมดเพื่อสร้างคลาสให้คุณ (Java, C ++ หรือ C #) คลาสที่สร้างขึ้นทั้งหมดมีตัวแยกวิเคราะห์ข้อความและไบนารีซึ่งทำให้พวกเขาดีสำหรับการเริ่มต้นข้อความที่ใช้ข้อความและอนุกรม


ศูนย์กลางการรับส่งข้อความของฉันคือหลักโปรแกรมของฉันคุณรู้หรือไม่ว่าบัฟเฟอร์โปรโตคอลเกิดค่าใช้จ่ายสูง
ไบรอัน

ฉันไม่คิดว่าพวกเขามีค่าใช้จ่ายจำนวนมากเนื่องจาก API เป็นเพียงคลาส Builder สำหรับแต่ละข้อความและคลาสสำหรับข้อความเอง Google ใช้พวกเขาเป็นแกนหลักของโครงสร้างพื้นฐานของพวกเขา ตัวอย่างเช่นเอนทิตีของ Google App Engine ทั้งหมดจะถูกแปลงเป็นบัฟเฟอร์โปรโตคอลก่อนที่จะคงอยู่ หากคุณมีข้อสงสัยฉันขอแนะนำให้คุณใช้การทดสอบเปรียบเทียบระหว่างการใช้งานปัจจุบันและบัฟเฟอร์โปรโตคอล หากคุณคิดว่าค่าโสหุ้ยเป็นที่ยอมรับให้ใช้มัน
dsilva.vinicius
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.